17 Commits

Author SHA1 Message Date
d1d6d24dbb remove redundant Siteworx CA certificates installation steps from CI workflow
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m29s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Successful in 1m44s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 3m23s
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 4m51s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 6m4s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Failing after 35s
2026-02-06 20:20:25 -05:00
6e908bad17 bump frontend and backend image versions to v0.0.37 2026-02-06 20:10:21 -05:00
f6ed88fd78 ignore ArgoCD paths in push trigger for CI workflow
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m45s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Successful in 1m47s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 3m22s
2026-02-06 20:09:48 -05:00
b122fca494 add checkout step for release branch in CI build process
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Has been cancelled
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Has been cancelled
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Has been cancelled
2026-02-06 20:09:15 -05:00
1cc6d5ece4 update Go version in Dockerfile to 1.25.6
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m37s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Successful in 1m53s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 3m26s
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 5m39s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 6m41s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Failing after 1m51s
2026-02-06 19:54:37 -05:00
74ea300f80 update Go version and change utilities package import path
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m46s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Successful in 4m20s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 5m48s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Failing after 4m31s
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 6m15s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Has been skipped
2026-02-06 19:39:43 -05:00
f8958dfbef add automated build artifact recommit step in CI workflow
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m30s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Failing after 1m40s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Failing after 1m39s
2026-02-06 19:36:10 -05:00
22e045730f update dependencies and improve bullet manufacturer options deduplication
Some checks failed
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Failing after 1m49s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Failing after 2m6s
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 2m33s
2026-02-06 19:31:10 -05:00
a4edafdd2e update DB_HOST in configmap.yml to use service name
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 3m32s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Failing after 4m42s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Failing after 5m3s
2026-02-06 19:23:10 -05:00
f8974acab5 update DB_HOST in configmap.yml to use service name
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Has started running
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Has started running
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Has been cancelled
2026-02-06 19:22:24 -05:00
ac3cd505bf update DB_HOST in configmap.yml to use service name
Some checks are pending
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Has started running
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Has started running
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Has started running
2026-02-06 19:20:20 -05:00
03762a0be7 [create-pull-request] automated change (#10)
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 4m1s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Successful in 7m0s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 7m13s
Co-authored-by: rrise <+rrise@users.noreply.github.com>
Reviewed-on: Siteworxpro/reloading-manager#10
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
2025-06-11 02:04:49 +00:00
0f915ccd82 happy monday _ bleh _ (#9)
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m23s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Successful in 1m32s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 3m35s
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 6m11s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 6m47s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Failing after 53s
Reviewed-on: Siteworxpro/reloading-manager#9
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
2025-06-11 01:43:53 +00:00
dd383b6fb3 fix tpyo (#8)
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 7m28s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Successful in 7m40s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 10m24s
Reviewed-on: Siteworxpro/reloading-manager#8
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
2025-06-10 15:56:03 +00:00
e484aa7e31 tagging release w.t.f.
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 5m58s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 9m2s
2025-05-16 21:18:03 -04:00
3c60c1b012 [create-pull-request] automated change (#7)
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 6m18s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 9m20s
Co-authored-by: rrise <+rrise@users.noreply.github.com>
Reviewed-on: Siteworxpro/reloading-manager#7
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
2025-05-16 15:34:23 -04:00
c5f1f32b44 You know the rules and so do I
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 10m30s
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 19m6s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 20m46s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Failing after 1m18s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 22m13s
2025-05-16 14:05:49 -04:00
31 changed files with 914 additions and 316 deletions

View File

@@ -10,13 +10,6 @@ jobs:
name: 🖼️ 🔨 Build Frontend name: 🖼️ 🔨 Build Frontend
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 🛡️ 🔒 Add Siteworx CA Certificates
run: |
apt update && apt install -yq ca-certificates curl
curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates
- name: 📖 🔍 Checkout Repository Code - name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@@ -62,13 +55,6 @@ jobs:
name: 🖥️ 🔨 Build Backend name: 🖥️ 🔨 Build Backend
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 🛡️🔒 Add Siteworx CA Certificates
run: |
apt update && apt install -yq ca-certificates curl
curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates
- name: 📖🔍 Checkout Repository Code - name: 📖🔍 Checkout Repository Code
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@@ -111,13 +97,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [BuildFrontend, BuildBackend] needs: [BuildFrontend, BuildBackend]
steps: steps:
- name: 🛡️🔒 Add Siteworx CA Certificates
run: |
apt update && apt install -yq ca-certificates curl
curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates
- name: 📖 🔍 Checkout Repository Code - name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
@@ -127,18 +106,31 @@ jobs:
run: | run: |
echo "## Do not edit this file directly. It is auto-generated by the script." > argocd/deployment/deployment.yml echo "## Do not edit this file directly. It is auto-generated by the script." > argocd/deployment/deployment.yml
sed "s|__TAG__|${{ gitea.ref_name }}|g" argocd/template/deployment.yml >> argocd/deployment/deployment.yml sed "s|__TAG__|${{ gitea.ref_name }}|g" argocd/template/deployment.yml >> argocd/deployment/deployment.yml
#
# - name: 💾 ✅ Commit Updated Manifest - name: 📤 📦 Recommit Build Artifacts
# uses: EndBug/add-and-commit@v9 uses: addnab/docker-run-action@v3
# with: with:
# new_branch: release/${{ gitea.ref_name }}-deploy image: alpine/git
# add: argocd/deployment/deployment.yml options: --volumes-from ${{ env.JOB_CONTAINER_NAME }} -w ${{ gitea.workspace }}
# author_name: "GitHub Action 🤖" run: |
# author_email: gitia@siteworxpro.com mkdir -p ~/.ssh
# message: "📝 🔄 Update deployment manifest with new image tags" chmod 700 ~/.ssh
ssh-keyscan -H gitea.siteworxpro.com >> ~/.ssh/known_hosts
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
git config --global user.email "gitea@siteworxpro.com"
git config --global user.name "Gitea-Runner via Gitea Actions"
git config --global push.autoSetupRemote true
git remote rm origin && git remote add origin "git@gitea.siteworxpro.com:siteworxpro/reloading-manager.git"
git add -f "argocd/deployment/*" || true
git checkout -b release/${{ gitea.ref_name }}-deploy || git checkout release/${{ gitea.ref_name }}-deploy
git commit -m "Build Auto Commit" || echo "No changes to commit"
git push origin HEAD:${{ gitea.ref_name }} -o ci.skip || echo "No changes to push"
- name: 🚀 ✨ Create Pull Request - name: 🚀 ✨ Create Pull Request
uses: https://github.com/infinilabs/gitea-pr.git@v0 uses: peter-evans/create-pull-request@v7
env: env:
NODE_TLS_REJECT_UNAUTHORIZED: 0 NODE_TLS_REJECT_UNAUTHORIZED: 0
with: with:

View File

@@ -6,6 +6,8 @@ on:
required: true required: true
default: 'true' default: 'true'
push: push:
paths-ignore:
- argocd/**/*
branches: branches:
- "*" - "*"
@@ -38,6 +40,29 @@ jobs:
cd frontend cd frontend
npm run build npm run build
golangci-lint:
name: 🧪 🐹 GolangCI-Lint
runs-on: ubuntu-latest
steps:
- name: 🛡️ 🔒 Add Siteworx CA Certificates
run: |
apt update && apt install -yq ca-certificates curl
curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates
- name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: ⚙️ 🐹 Set up Go Environment
uses: actions/setup-go@v2
with:
go-version: '1.25.6'
cache: true
- name: ✅ 🧪 Run GolangCI-Lint
uses: golangci/golangci-lint-action@v8.0.0
with:
working-directory: backend
test-go: test-go:
env: env:
GOPRIVATE: 'git.siteworxpro.com' GOPRIVATE: 'git.siteworxpro.com'
@@ -53,7 +78,7 @@ jobs:
- name: ⚙️ 🐹 Set up Go Environment - name: ⚙️ 🐹 Set up Go Environment
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: '1.24.3' go-version: '1.25.6'
cache: true cache: true
- name: 📖 🔍 Checkout Repository Code - name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2 uses: actions/checkout@v2

View File

@@ -3,7 +3,7 @@ kind: ConfigMap
metadata: metadata:
name: reloading-cm name: reloading-cm
data: data:
DB_HOST: "192.168.1.30" DB_HOST: "postgres.postgres.svc.cluster.local"
DB_DATABASE: "loading" DB_DATABASE: "loading"
DB_USER: "loading" DB_USER: "loading"
DB_PASSWORD: "loading" DB_PASSWORD: "loading"

View File

@@ -19,11 +19,11 @@ spec:
- name: siteworxpro - name: siteworxpro
containers: containers:
- name: frontend - name: frontend
image: scr.siteworxpro.com/reloading-manager/frontend:v0.0.32 image: scr.siteworxpro.com/reloading-manager/frontend:v0.0.37
ports: ports:
- containerPort: 80 - containerPort: 80
- name: backend - name: backend
image: scr.siteworxpro.com/reloading-manager/backend:v0.0.32 image: scr.siteworxpro.com/reloading-manager/backend:v0.0.37
ports: ports:
- containerPort: 8080 - containerPort: 8080
envFrom: envFrom:

17
backend/.golangci.yml Normal file
View File

@@ -0,0 +1,17 @@
version: "2"
linters:
default: standard
enable:
- whitespace
- tagalign
- reassign
- bodyclose
- contextcheck
- containedctx
- godot
- usestdlibvars
formatters:
settings:
gofmt:
simplify: true

View File

@@ -1,4 +1,4 @@
FROM siteworxpro/golang:1.24.3 AS build FROM siteworxpro/golang:1.25.6 AS build
WORKDIR /app WORKDIR /app

View File

@@ -4,7 +4,7 @@ docker run -v $(pwd)/postgres:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=password \ -e POSTGRES_PASSWORD=password \
--rm --name postgres \ --rm --name postgres \
-p 5432:5432 \ -p 5432:5432 \
-d scr.siteworxpro.com/library/postgres:17 -d postgres:17
``` ```
```shell ```shell

View File

@@ -3,12 +3,12 @@ package database
import ( import (
"context" "context"
"fmt" "fmt"
"git.siteworxpro.com/packages/go/utilities/Env"
"git.siteworxpro.com/reloading-manager/backend/models/bullets" "git.siteworxpro.com/reloading-manager/backend/models/bullets"
"git.siteworxpro.com/reloading-manager/backend/models/loads" "git.siteworxpro.com/reloading-manager/backend/models/loads"
"git.siteworxpro.com/reloading-manager/backend/models/manufacturer" "git.siteworxpro.com/reloading-manager/backend/models/manufacturer"
"git.siteworxpro.com/reloading-manager/backend/models/powder" "git.siteworxpro.com/reloading-manager/backend/models/powder"
"git.siteworxpro.com/reloading-manager/backend/models/primers" "git.siteworxpro.com/reloading-manager/backend/models/primers"
"gitea.siteworxpro.com/golang-packages/utilities/Env"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"log" "log"
) )
@@ -20,6 +20,10 @@ const (
DbPassword Env.EnvironmentVariable = "DB_PASSWORD" DbPassword Env.EnvironmentVariable = "DB_PASSWORD"
) )
type contextKeyType string
const dbContextKey contextKeyType = "dbcontext"
type Database struct { type Database struct {
Db *pgx.Conn Db *pgx.Conn
connected bool connected bool
@@ -50,6 +54,24 @@ func (*Database) DSN(hidePassword bool) string {
return fmt.Sprintf("postgres://%s:%s@%s:5432/%s%s", dbUser, dbPassword, dbHost, dbDatabase, extraParams) return fmt.Sprintf("postgres://%s:%s@%s:5432/%s%s", dbUser, dbPassword, dbHost, dbDatabase, extraParams)
} }
func NewWithContext(ctx context.Context) context.Context {
db := GetNewDatabase()
return context.WithValue(ctx, dbContextKey, db)
}
func NewFromContext(ctx context.Context) *Database {
if ok := ctx.Value(dbContextKey); ok != nil {
return ctx.Value(dbContextKey).(*Database)
}
return nil
}
func WithContext(ctx context.Context, database *Database) context.Context {
return context.WithValue(ctx, dbContextKey, database)
}
func GetNewDatabase() *Database { func GetNewDatabase() *Database {
var dbSingleton Database var dbSingleton Database

View File

@@ -11,6 +11,9 @@ import (
func (db *Database) Migrate() { func (db *Database) Migrate() {
sqlDB, err := sql.Open("postgres", db.DSN(false)) sqlDB, err := sql.Open("postgres", db.DSN(false))
if err != nil {
log.Fatal(err)
}
driver, err := postgres.WithInstance(sqlDB, &postgres.Config{ driver, err := postgres.WithInstance(sqlDB, &postgres.Config{
MigrationsTable: "schema_migrations", MigrationsTable: "schema_migrations",

View File

@@ -1,16 +1,16 @@
module git.siteworxpro.com/reloading-manager/backend module git.siteworxpro.com/reloading-manager/backend
go 1.24.3 go 1.25.6
require ( require (
git.siteworxpro.com/packages/go/utilities v1.3.0 gitea.siteworxpro.com/golang-packages/utilities v1.0.0
github.com/go-jet/jet/v2 v2.13.0 github.com/go-jet/jet/v2 v2.13.0
github.com/go-playground/validator v9.31.0+incompatible github.com/go-playground/validator v9.31.0+incompatible
github.com/go-sql-driver/mysql v1.9.2 github.com/go-sql-driver/mysql v1.9.2
github.com/golang-migrate/migrate v3.5.4+incompatible github.com/golang-migrate/migrate v3.5.4+incompatible
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/jackc/pgx/v5 v5.7.4 github.com/jackc/pgx/v5 v5.7.5
github.com/labstack/echo/v4 v4.13.3 github.com/labstack/echo/v4 v4.13.4
github.com/labstack/gommon v0.4.2 github.com/labstack/gommon v0.4.2
) )
@@ -41,11 +41,11 @@ require (
github.com/stretchr/testify v1.10.0 // indirect github.com/stretchr/testify v1.10.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.37.0 // indirect golang.org/x/crypto v0.39.0 // indirect
golang.org/x/net v0.39.0 // indirect golang.org/x/net v0.41.0 // indirect
golang.org/x/sys v0.32.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.24.0 // indirect golang.org/x/text v0.26.0 // indirect
golang.org/x/time v0.11.0 // indirect golang.org/x/time v0.12.0 // indirect
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@@ -1,7 +1,7 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.siteworxpro.com/packages/go/utilities v1.3.0 h1:931q66COBJATgIQksPDSZlWMIwENJhhfC/GVf22ER5s= gitea.siteworxpro.com/golang-packages/utilities v1.0.0 h1:f5JqAeZWBn/HBO9k5dzg0Wm91a69uwU5UC2P9ebQ9J0=
git.siteworxpro.com/packages/go/utilities v1.3.0/go.mod h1:iWhICNrMnB03PY9dM9eCNs9uQPEsPwae5pJDG+HHUPI= gitea.siteworxpro.com/golang-packages/utilities v1.0.0/go.mod h1:QNqclnfv/BT2D5tbXgsGm7uhhe2Baovi5F6j0pVvMGc=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -40,8 +40,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.4 h1:9wKznZrhWa2QiHL+NjTSPP6yjl3451BX3imWDnokYlg= github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -50,8 +50,8 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= github.com/labstack/echo/v4 v4.13.4 h1:oTZZW+T3s9gAu5L8vmzihV7/lkXGZuITzTQkTEhcXEA=
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g= github.com/labstack/echo/v4 v4.13.4/go.mod h1:g63b33BZ5vZzcIUF8AtRH40DrTlXnx4UMC8rBdndmjQ=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
@@ -86,41 +86,41 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -21,12 +21,15 @@ type BulletResponse struct {
func Photo(c echo.Context) error { func Photo(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
defer func() {
_ = db.Db.Close(context.Background())
}()
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID format")
} }
byId, err := db.Bullets.GetBulletById(context.Background(), *uid) byId, err := db.Bullets.GetBulletById(context.Background(), *uid)
@@ -48,15 +51,18 @@ func Photo(c echo.Context) error {
func Delete(c echo.Context) error { func Delete(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background())
defer func() {
_ = db.Db.Close(context.Background())
}()
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID format")
} }
err := db.Bullets.DeleteBullet(context.Background(), *uid) err = db.Bullets.DeleteBullet(context.Background(), *uid)
if err != nil { if err != nil {
return err return err
} }
@@ -66,12 +72,14 @@ func Delete(c echo.Context) error {
func Put(c echo.Context) error { func Put(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID format")
} }
byId, err := db.Bullets.GetBulletById(context.Background(), *uid) byId, err := db.Bullets.GetBulletById(context.Background(), *uid)
@@ -101,9 +109,9 @@ func Put(c echo.Context) error {
weight, _ := strconv.ParseInt(c.FormValue("weight"), 10, 32) weight, _ := strconv.ParseInt(c.FormValue("weight"), 10, 32)
diameter, _ := strconv.ParseInt(c.FormValue("diameter"), 10, 32) diameter, _ := strconv.ParseInt(c.FormValue("diameter"), 10, 32)
manufacturerId := c.FormValue("manufacturer_id") manufacturerId := c.FormValue("manufacturer_id")
manufacturerUid := handlers.ParseUuidOrBadRequest(c, manufacturerId) manufacturerUid, err := handlers.ParseUuidOrBadRequest(c, manufacturerId)
if manufacturerUid == nil { if err == nil || manufacturerUid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID format")
} }
name := c.FormValue("name") name := c.FormValue("name")
@@ -147,13 +155,15 @@ func Put(c echo.Context) error {
func Get(c echo.Context) error { func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
if c.Param("id") != "" { if c.Param("id") != "" {
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID format")
} }
byId, err := db.Bullets.GetBulletById(context.Background(), *uid) byId, err := db.Bullets.GetBulletById(context.Background(), *uid)
@@ -210,7 +220,6 @@ func Get(c echo.Context) error {
} }
func Post(c echo.Context) error { func Post(c echo.Context) error {
file, err := c.FormFile("photo") file, err := c.FormFile("photo")
if err != nil { if err != nil {
c.Logger().Error(err) c.Logger().Error(err)
@@ -245,11 +254,13 @@ func Post(c echo.Context) error {
} }
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
manufacturerUid := handlers.ParseUuidOrBadRequest(c, manufacturerId) manufacturerUid, err := handlers.ParseUuidOrBadRequest(c, manufacturerId)
if manufacturerUid == nil { if err != nil || manufacturerUid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID format")
} }
manufacturer, err := db.Manufacturer.GetById(context.Background(), *manufacturerUid) manufacturer, err := db.Manufacturer.GetById(context.Background(), *manufacturerUid)

View File

@@ -22,7 +22,9 @@ type postRequest struct {
func Get(c echo.Context) error { func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
cartridges, err := db.Loads.GetCartridges(context.Background()) cartridges, err := db.Loads.GetCartridges(context.Background())
if err != nil { if err != nil {
@@ -45,7 +47,9 @@ func Get(c echo.Context) error {
func Post(c echo.Context) error { func Post(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
req := postRequest{} req := postRequest{}
@@ -79,14 +83,16 @@ func Post(c echo.Context) error {
func Delete(c echo.Context) error { func Delete(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
uid := handlers.ParseUuidOrBadRequest(c, c.Param("id")) uid, err := handlers.ParseUuidOrBadRequest(c, c.Param("id"))
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "invalid id")
} }
err := db.Loads.DeleteCartridge(context.Background(), *uid) err = db.Loads.DeleteCartridge(context.Background(), *uid)
if err != nil { if err != nil {
return err return err

View File

@@ -2,18 +2,12 @@ package handlers
import ( import (
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"net/http"
) )
func ReadFile(c echo.Context, formName string) ([]byte, error) { func ReadFile(c echo.Context, formName string) ([]byte, error) {
file, err := c.FormFile(formName) file, err := c.FormFile(formName)
if err != nil { if err != nil {
c.Logger().Error(err) c.Logger().Error(err)
_ = c.JSON(http.StatusBadRequest, struct {
Message string `json:"message"`
}{
Message: "No file provided",
})
return nil, err return nil, err
} }

View File

@@ -2,7 +2,6 @@ package loads
import ( import (
"context" "context"
"fmt"
"git.siteworxpro.com/reloading-manager/backend/.gen/loading/public/table" "git.siteworxpro.com/reloading-manager/backend/.gen/loading/public/table"
"git.siteworxpro.com/reloading-manager/backend/database" "git.siteworxpro.com/reloading-manager/backend/database"
"git.siteworxpro.com/reloading-manager/backend/handlers" "git.siteworxpro.com/reloading-manager/backend/handlers"
@@ -10,8 +9,10 @@ import (
"git.siteworxpro.com/reloading-manager/backend/handlers/primers" "git.siteworxpro.com/reloading-manager/backend/handlers/primers"
"git.siteworxpro.com/reloading-manager/backend/models/loads" "git.siteworxpro.com/reloading-manager/backend/models/loads"
"github.com/go-jet/jet/v2/postgres" "github.com/go-jet/jet/v2/postgres"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"mime"
"net/http" "net/http"
"strings" "strings"
) )
@@ -45,6 +46,7 @@ type row struct {
type loadResponseResults struct { type loadResponseResults struct {
Id string `json:"id"` Id string `json:"id"`
Cartridge string `json:"cartridge"` Cartridge string `json:"cartridge"`
CartridgeId string `json:"cartridge_id"`
Col float32 `json:"col"` Col float32 `json:"col"`
Powder handlers.Powder `json:"powder"` Powder handlers.Powder `json:"powder"`
PowderGr float32 `json:"powder_gr"` PowderGr float32 `json:"powder_gr"`
@@ -63,8 +65,28 @@ type ResultChan[T any] struct {
} }
func Post(c echo.Context) error { func Post(c echo.Context) error {
var exists *loads.GetLoadByIdRow
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
id := c.Param("id")
if id != "" {
uuid, err := handlers.ParseUuid(id)
if err != nil {
return handlers.BadRequest(c, "id is not a valid UUID")
}
gbi, err := db.Loads.GetLoadById(context.Background(), *uuid)
if err != nil || !gbi.ID.Valid {
return handlers.NotFound(c, "load not found")
}
exists = &gbi
}
cartridgeID, err := handlers.ParseUuid(c.FormValue("cartridge_id")) cartridgeID, err := handlers.ParseUuid(c.FormValue("cartridge_id"))
if err != nil { if err != nil {
@@ -87,8 +109,11 @@ func Post(c echo.Context) error {
} }
file, err := handlers.ReadFile(c, "photo") file, err := handlers.ReadFile(c, "photo")
if err != nil { if err != nil && exists == nil {
return handlers.BadRequest(c, "photo is not valid") return handlers.BadRequest(c, "photo is not valid")
} else if err != nil {
// If we are updating an existing load, we can ignore the error
file = exists.Photo
} }
meta := c.FormValue("meta") meta := c.FormValue("meta")
@@ -115,6 +140,26 @@ func Post(c echo.Context) error {
return handlers.BadRequest(c, "col is not valid") return handlers.BadRequest(c, "col is not valid")
} }
if exists != nil {
err = db.Loads.UpdateLoad(context.Background(), loads.UpdateLoadParams{
ID: exists.ID,
CartridgeID: *cartridgeID,
Col: colFl,
PowderID: *powderId,
PowderGr: powderGrFl,
PrimerID: *primerId,
BulletID: *bulletId,
Photo: file,
Meta: []byte(meta),
})
if err != nil {
return err
}
return c.JSON(http.StatusOK, handlers.Response[string]{Payload: exists.ID.String()})
}
uid, err := db.Loads.CreateLoad(context.Background(), loads.CreateLoadParams{ uid, err := db.Loads.CreateLoad(context.Background(), loads.CreateLoadParams{
CartridgeID: *cartridgeID, CartridgeID: *cartridgeID,
Col: colFl, Col: colFl,
@@ -133,16 +178,66 @@ func Post(c echo.Context) error {
return c.JSON(http.StatusCreated, handlers.Response[string]{Payload: uid.String()}) return c.JSON(http.StatusCreated, handlers.Response[string]{Payload: uid.String()})
} }
func Photo(c echo.Context) error {
id := c.Param("id")
if id == "" {
return handlers.BadRequest(c, "id is required")
}
uuid, err := handlers.ParseUuid(id)
if err != nil {
return handlers.BadRequest(c, "id is not a valid UUID")
}
db := c.(*database.CustomContext).Db
defer func() {
_ = db.Db.Close(context.Background())
}()
file, err := db.Loads.GetLoadById(context.Background(), *uuid)
if err != nil {
return handlers.NotFound(c, "load photo not found")
}
mt, _, _ := mime.ParseMediaType(string(file.Photo))
return c.Blob(http.StatusOK, mt, file.Photo)
}
func Get(c echo.Context) error { func Get(c echo.Context) error {
cTotal := make(chan ResultChan[int64]) id := c.Param("id")
cResults := make(chan ResultChan[[]loadResponseResults]) 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]) { go func(ch chan ResultChan[int64]) {
db := database.GetNewDatabase() 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) q := getQuery(c, true)
if q == nil {
ch <- ResultChan[int64]{Result: 0}
return
}
sql, params := q.Sql() sql, params := q.Sql()
var total int64 var total int64
@@ -155,24 +250,41 @@ func Get(c echo.Context) error {
} else { } else {
ch <- ResultChan[int64]{Result: total} ch <- ResultChan[int64]{Result: total}
} }
}(cTotal) }(cTotal)
go execResultsQuery(cResults, c)
go func(ch chan ResultChan[[]loadResponseResults]) { total := <-cTotal
if total.Err != nil {
return total.Err
}
results := <-cResults
if results.Err != nil {
return results.Err
}
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() 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, false) q := getQuery(c, false)
fmt.Println(q.DebugSql()) if q == nil {
ch <- ResultChan[[]loadResponseResults]{Result: []loadResponseResults{}}
return
}
sql, params := q.Sql() sql, params := q.Sql()
rows, err := db.Db.Query(context.Background(), sql, params...) rows, err := db.Db.Query(context.Background(), sql, params...)
if err != nil { if err != nil {
ch <- ResultChan[[]loadResponseResults]{Err: err} ch <- ResultChan[[]loadResponseResults]{Err: err}
return return
} }
@@ -218,6 +330,7 @@ func Get(c echo.Context) error {
results = append(results, loadResponseResults{ results = append(results, loadResponseResults{
Id: row.ID.String(), Id: row.ID.String(),
Cartridge: row.CartridgeName, Cartridge: row.CartridgeName,
CartridgeId: row.CartridgeID.String(),
Col: row.Col, Col: row.Col,
Powder: handlers.Powder{ Powder: handlers.Powder{
Id: row.PowderID.String(), Id: row.PowderID.String(),
@@ -251,19 +364,6 @@ func Get(c echo.Context) error {
} }
ch <- ResultChan[[]loadResponseResults]{Result: results} ch <- ResultChan[[]loadResponseResults]{Result: results}
}(cResults)
total := <-cTotal
if total.Err != nil {
return total.Err
}
results := <-cResults
if results.Err != nil {
return results.Err
}
return c.JSON(http.StatusOK, handlers.Response[loadResponse]{Status: http.StatusText(http.StatusOK), Payload: loadResponse{Total: int(total.Result), Results: results.Result}})
} }
func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement { func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement {
@@ -289,7 +389,6 @@ func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement {
if countOnly { if countOnly {
q = tb.SELECT(postgres.COUNT(l.ID).AS("total")) q = tb.SELECT(postgres.COUNT(l.ID).AS("total"))
} else { } else {
q = tb.SELECT( q = tb.SELECT(
// Load // Load
l.ID.AS("id"), l.ID.AS("id"),
@@ -329,6 +428,17 @@ func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement {
// where expressions // where expressions
expressions := make([]postgres.BoolExpression, 0) 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") != "" { if c.QueryParam("cartridge_id") != "" {
ids := strings.Split(c.QueryParam("cartridge_id"), ",") ids := strings.Split(c.QueryParam("cartridge_id"), ",")
if len(ids) > 0 { if len(ids) > 0 {
@@ -438,17 +548,48 @@ func getQuery(c echo.Context, countOnly bool) postgres.SelectStatement {
if limit == "" { if limit == "" {
limit = "50" limit = "50"
} }
offset := c.QueryParam("offset")
if offset == "" { pageInt := handlers.ParseInt64OrDefault(c.QueryParam("page"), 1)
offset = "0" if pageInt < 1 {
pageInt = 1
} }
offset := (pageInt - 1) * handlers.ParseInt64OrDefault(limit, 50)
q = q.LIMIT(handlers.ParseInt64OrDefault(limit, 50)). q = q.LIMIT(handlers.ParseInt64OrDefault(limit, 50)).
OFFSET(handlers.ParseInt64OrDefault(offset, 0)) OFFSET(offset)
return q return q
} }
func Delete(c echo.Context) error {
id := c.Param("id")
if id == "" {
return handlers.BadRequest(c, "id is required")
}
uuid, err := handlers.ParseUuid(id)
if err != nil {
return handlers.BadRequest(c, "id is not a valid UUID")
}
db := c.(*database.CustomContext).Db
defer func() {
_ = db.Db.Close(context.Background())
}()
exists, err := db.Loads.GetLoadById(context.Background(), *uuid)
if err != nil || !exists.ID.Valid {
return handlers.NotFound(c, "load not found")
}
err = db.Loads.DeleteLoad(context.Background(), *uuid)
if err != nil {
return err
}
return c.NoContent(http.StatusNoContent)
}
func getUuidExpr(ids []string) []postgres.Expression { func getUuidExpr(ids []string) []postgres.Expression {
expr := make([]postgres.Expression, 0) expr := make([]postgres.Expression, 0)
for _, id := range ids { for _, id := range ids {

View File

@@ -21,13 +21,15 @@ type manufacturerResponse struct {
func Get(c echo.Context) error { func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
if c.Param("id") != "" { if c.Param("id") != "" {
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID format")
} }
byId, err := db.Manufacturer.GetById(context.Background(), *uid) byId, err := db.Manufacturer.GetById(context.Background(), *uid)
@@ -73,15 +75,17 @@ func Get(c echo.Context) error {
func Delete(c echo.Context) error { func Delete(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID format")
} }
_, err := db.Manufacturer.GetById(context.Background(), *uid) _, err = db.Manufacturer.GetById(context.Background(), *uid)
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found") return echo.NewHTTPError(http.StatusNotFound, "Not found")
} }
@@ -97,16 +101,18 @@ func Delete(c echo.Context) error {
func Post(c echo.Context) error { func Post(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
if c.Param("id") != "" { if c.Param("id") != "" {
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID format")
} }
_, err := db.Manufacturer.GetById(context.Background(), *uid) _, err = db.Manufacturer.GetById(context.Background(), *uid)
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "Not found") return echo.NewHTTPError(http.StatusNotFound, "Not found")
} }

View File

@@ -13,7 +13,9 @@ import (
func Photo(c echo.Context) error { func Photo(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
id := c.Param("id") id := c.Param("id")
uid, err := handlers.ParseUuid(id) uid, err := handlers.ParseUuid(id)
@@ -41,7 +43,9 @@ func Photo(c echo.Context) error {
func Delete(c echo.Context) error { func Delete(c echo.Context) error {
id := c.Param("id") id := c.Param("id")
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
uid, err := handlers.ParseUuid(id) uid, err := handlers.ParseUuid(id)
if err != nil { if err != nil {
@@ -58,7 +62,9 @@ func Delete(c echo.Context) error {
func Post(c echo.Context) error { func Post(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
if c.Param("id") != "" { if c.Param("id") != "" {
id := c.Param("id") id := c.Param("id")
@@ -163,7 +169,9 @@ func Post(c echo.Context) error {
func Get(c echo.Context) error { func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
if c.Param("id") != "" { if c.Param("id") != "" {
id := c.Param("id") id := c.Param("id")

View File

@@ -3,6 +3,7 @@ package primers
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"git.siteworxpro.com/reloading-manager/backend/database" "git.siteworxpro.com/reloading-manager/backend/database"
"git.siteworxpro.com/reloading-manager/backend/handlers" "git.siteworxpro.com/reloading-manager/backend/handlers"
"git.siteworxpro.com/reloading-manager/backend/models/primers" "git.siteworxpro.com/reloading-manager/backend/models/primers"
@@ -19,7 +20,9 @@ type PrimerResponse struct {
func Delete(c echo.Context) error { func Delete(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
id := c.Param("id") id := c.Param("id")
uid, err := handlers.ParseUuid(id) uid, err := handlers.ParseUuid(id)
@@ -37,13 +40,15 @@ func Delete(c echo.Context) error {
func Post(c echo.Context) error { func Post(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
if c.Param("id") != "" { if c.Param("id") != "" {
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID.")
} }
p, err := db.Primer.GetPrimerById(context.Background(), *uid) p, err := db.Primer.GetPrimerById(context.Background(), *uid)
@@ -56,9 +61,9 @@ func Post(c echo.Context) error {
} }
if c.FormValue("manufacturer_id") != "" { if c.FormValue("manufacturer_id") != "" {
mid := handlers.ParseUuidOrBadRequest(c, c.FormValue("manufacturer_id")) mid, err := handlers.ParseUuidOrBadRequest(c, c.FormValue("manufacturer_id"))
if mid == nil { if err != nil || mid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid Manufacturer ID.")
} }
p.ManufacturerID = *mid p.ManufacturerID = *mid
@@ -112,13 +117,14 @@ func Post(c echo.Context) error {
if metaString == "" { if metaString == "" {
metaString = "{}" metaString = "{}"
} }
var meta json.RawMessage = []byte(metaString)
meta := []byte(metaString)
newUuid := uuid.New().String() newUuid := uuid.New().String()
uid, _ := handlers.ParseUuid(newUuid) uid, _ := handlers.ParseUuid(newUuid)
mid := handlers.ParseUuidOrBadRequest(c, manufacturerId) mid, err := handlers.ParseUuidOrBadRequest(c, manufacturerId)
if mid == nil { if err != nil || mid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid Manufacturer ID.")
} }
err = db.Primer.InsertPrimer(context.Background(), primers.InsertPrimerParams{ err = db.Primer.InsertPrimer(context.Background(), primers.InsertPrimerParams{
@@ -145,12 +151,14 @@ func Post(c echo.Context) error {
func Photo(c echo.Context) error { func Photo(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID.")
} }
byId, err := db.Primer.GetPrimerById(context.Background(), *uid) byId, err := db.Primer.GetPrimerById(context.Background(), *uid)
@@ -172,18 +180,20 @@ func Photo(c echo.Context) error {
func Get(c echo.Context) error { func Get(c echo.Context) error {
db := c.(*database.CustomContext).Db db := c.(*database.CustomContext).Db
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
if c.Param("id") != "" { if c.Param("id") != "" {
id := c.Param("id") id := c.Param("id")
uid := handlers.ParseUuidOrBadRequest(c, id) uid, err := handlers.ParseUuidOrBadRequest(c, id)
if uid == nil { if err != nil || uid == nil {
return nil return echo.NewHTTPError(http.StatusBadRequest, "Invalid UUID.")
} }
row, err := db.Primer.GetPrimerById(context.Background(), *uid) row, err := db.Primer.GetPrimerById(context.Background(), *uid)
if err != nil { if err != nil {
return err return fmt.Errorf("primer not found: %v", err)
} }
return c.JSON(http.StatusOK, handlers.Response[PrimerResponse]{ return c.JSON(http.StatusOK, handlers.Response[PrimerResponse]{

View File

@@ -11,7 +11,6 @@ type TestContext struct {
} }
func (t TestContext) JSON(code int, i interface{}) error { func (t TestContext) JSON(code int, i interface{}) error {
if code != 400 { if code != 400 {
t.t.Fatal("expected 400") t.t.Fatal("expected 400")
} }

View File

@@ -1,6 +1,7 @@
package handlers package handlers
import ( import (
"fmt"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
@@ -23,7 +24,7 @@ func ParseUuidOrEmpty(s string) *pgtype.UUID {
func ParseUuid(s string) (*pgtype.UUID, error) { func ParseUuid(s string) (*pgtype.UUID, error) {
uid, err := uuid.Parse(s) uid, err := uuid.Parse(s)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("invalid UUID format: %v", err)
} }
return &pgtype.UUID{ return &pgtype.UUID{
@@ -32,14 +33,11 @@ func ParseUuid(s string) (*pgtype.UUID, error) {
}, nil }, nil
} }
func ParseUuidOrBadRequest(c echo.Context, s string) *pgtype.UUID { func ParseUuidOrBadRequest(c echo.Context, s string) (*pgtype.UUID, error) {
uid, err := ParseUuid(s) uid, err := ParseUuid(s)
if err != nil { if err != nil {
_ = BadRequest(c, "Invalid UUID.") return nil, BadRequest(c, fmt.Sprintf("invalid UUID. %v", err))
return nil
} }
return uid return uid, nil
} }

View File

@@ -3,7 +3,6 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"git.siteworxpro.com/packages/go/utilities/Env"
"git.siteworxpro.com/reloading-manager/backend/database" "git.siteworxpro.com/reloading-manager/backend/database"
"git.siteworxpro.com/reloading-manager/backend/handlers/bullets" "git.siteworxpro.com/reloading-manager/backend/handlers/bullets"
"git.siteworxpro.com/reloading-manager/backend/handlers/cartridge" "git.siteworxpro.com/reloading-manager/backend/handlers/cartridge"
@@ -11,6 +10,7 @@ import (
"git.siteworxpro.com/reloading-manager/backend/handlers/manufacturer" "git.siteworxpro.com/reloading-manager/backend/handlers/manufacturer"
"git.siteworxpro.com/reloading-manager/backend/handlers/powder" "git.siteworxpro.com/reloading-manager/backend/handlers/powder"
"git.siteworxpro.com/reloading-manager/backend/handlers/primers" "git.siteworxpro.com/reloading-manager/backend/handlers/primers"
"gitea.siteworxpro.com/golang-packages/utilities/Env"
"github.com/go-playground/validator" "github.com/go-playground/validator"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware" "github.com/labstack/echo/v4/middleware"
@@ -98,7 +98,11 @@ func main() {
// loads // loads
e.GET("/load", loads.Get) e.GET("/load", loads.Get)
e.GET("/load/:id", loads.Get)
e.GET("/load/:id/photo", loads.Photo)
e.POST("/load", loads.Post) e.POST("/load", loads.Post)
e.POST("/load/:id", loads.Post)
e.DELETE("/load/:id", loads.Delete)
addr := fmt.Sprintf("0.0.0.0:%s", Port.GetEnvString("8080")) addr := fmt.Sprintf("0.0.0.0:%s", Port.GetEnvString("8080"))
@@ -113,7 +117,9 @@ func migrate(e *echo.Echo) {
db := database.GetNewDatabase() db := database.GetNewDatabase()
defer db.Db.Close(context.Background()) defer func() {
_ = db.Db.Close(context.Background())
}()
db.Migrate() db.Migrate()
e.Logger.Info("✅ Complete!") e.Logger.Info("✅ Complete!")

View File

@@ -18,6 +18,22 @@ delete
from cartridges from cartridges
where id = $1; where id = $1;
-- name: DeleteLoad :exec
delete from loads
where id = $1;
-- name: UpdateLoad :exec
update loads set
cartridge_id = $1,
col = $2,
powder_id = $3,
powder_gr = $4,
primer_id = $5,
bullet_id = $6,
photo = $7,
meta = $8
where id = $9;
-- name: CreateLoad :one -- name: CreateLoad :one
insert into loads (cartridge_id, col, powder_id, powder_gr, primer_id, bullet_id, photo, meta) insert into loads (cartridge_id, col, powder_id, powder_gr, primer_id, bullet_id, photo, meta)
values ($1, $2, $3, $4, $5, $6, $7, $8) values ($1, $2, $3, $4, $5, $6, $7, $8)
@@ -25,6 +41,7 @@ returning id;
-- name: GetLoadById :one -- name: GetLoadById :one
select l.id as id, select l.id as id,
l.photo as photo,
c.id as cartridge_id, c.id as cartridge_id,
c.name as cartridge_name, c.name as cartridge_name,
c.meta as cartridge_meta, c.meta as cartridge_meta,

View File

@@ -73,6 +73,16 @@ func (q *Queries) DeleteCartridge(ctx context.Context, id pgtype.UUID) error {
return err return err
} }
const deleteLoad = `-- name: DeleteLoad :exec
delete from loads
where id = $1
`
func (q *Queries) DeleteLoad(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteLoad, id)
return err
}
const getCartridgeById = `-- name: GetCartridgeById :one const getCartridgeById = `-- name: GetCartridgeById :one
select c.id as id, c.name, c.meta select c.id as id, c.name, c.meta
from cartridges c from cartridges c
@@ -126,6 +136,7 @@ func (q *Queries) GetCartridges(ctx context.Context) ([]GetCartridgesRow, error)
const getLoadById = `-- name: GetLoadById :one const getLoadById = `-- name: GetLoadById :one
select l.id as id, select l.id as id,
l.photo as photo,
c.id as cartridge_id, c.id as cartridge_id,
c.name as cartridge_name, c.name as cartridge_name,
c.meta as cartridge_meta, c.meta as cartridge_meta,
@@ -147,6 +158,7 @@ where l.id = $1
type GetLoadByIdRow struct { type GetLoadByIdRow struct {
ID pgtype.UUID `json:"id"` ID pgtype.UUID `json:"id"`
Photo []byte `json:"photo"`
CartridgeID pgtype.UUID `json:"cartridge_id"` CartridgeID pgtype.UUID `json:"cartridge_id"`
CartridgeName string `json:"cartridge_name"` CartridgeName string `json:"cartridge_name"`
CartridgeMeta []byte `json:"cartridge_meta"` CartridgeMeta []byte `json:"cartridge_meta"`
@@ -165,6 +177,7 @@ func (q *Queries) GetLoadById(ctx context.Context, id pgtype.UUID) (GetLoadByIdR
var i GetLoadByIdRow var i GetLoadByIdRow
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,
&i.Photo,
&i.CartridgeID, &i.CartridgeID,
&i.CartridgeName, &i.CartridgeName,
&i.CartridgeMeta, &i.CartridgeMeta,
@@ -376,3 +389,43 @@ func (q *Queries) TotalLoads(ctx context.Context) (int64, error) {
err := row.Scan(&count) err := row.Scan(&count)
return count, err return count, err
} }
const updateLoad = `-- name: UpdateLoad :exec
update loads set
cartridge_id = $1,
col = $2,
powder_id = $3,
powder_gr = $4,
primer_id = $5,
bullet_id = $6,
photo = $7,
meta = $8
where id = $9
`
type UpdateLoadParams struct {
CartridgeID pgtype.UUID `json:"cartridge_id"`
Col float32 `json:"col"`
PowderID pgtype.UUID `json:"powder_id"`
PowderGr float32 `json:"powder_gr"`
PrimerID pgtype.UUID `json:"primer_id"`
BulletID pgtype.UUID `json:"bullet_id"`
Photo []byte `json:"photo"`
Meta []byte `json:"meta"`
ID pgtype.UUID `json:"id"`
}
func (q *Queries) UpdateLoad(ctx context.Context, arg UpdateLoadParams) error {
_, err := q.db.Exec(ctx, updateLoad,
arg.CartridgeID,
arg.Col,
arg.PowderID,
arg.PowderGr,
arg.PrimerID,
arg.BulletID,
arg.Photo,
arg.Meta,
arg.ID,
)
return err
}

View File

@@ -1 +1 @@
v22.14.0 v25.4.0

View File

@@ -1685,13 +1685,13 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.8.4", "version": "1.13.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.4.tgz",
"integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "integrity": "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
"form-data": "^4.0.0", "form-data": "^4.0.4",
"proxy-from-env": "^1.1.0" "proxy-from-env": "^1.1.0"
} }
}, },
@@ -1703,9 +1703,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "2.0.1", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2031,14 +2031,15 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.2", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
@@ -2758,6 +2759,51 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.3"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tinyglobby/node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/to-regex-range": { "node_modules/to-regex-range": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -2817,14 +2863,17 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "6.2.2", "version": "6.4.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.2.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
"integrity": "sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.4.4",
"picomatch": "^4.0.2",
"postcss": "^8.5.3", "postcss": "^8.5.3",
"rollup": "^4.30.1" "rollup": "^4.34.9",
"tinyglobby": "^0.2.13"
}, },
"bin": { "bin": {
"vite": "bin/vite.js" "vite": "bin/vite.js"
@@ -2887,6 +2936,35 @@
} }
} }
}, },
"node_modules/vite/node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/vite/node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/vscode-uri": { "node_modules/vscode-uri": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",

View File

@@ -0,0 +1,49 @@
<template>
<div class="loader" v-if="loading">
<div class="flex flex-col justify-center items-center">
<ProgressSpinner :style="{ width: '50px', height: '50px' }" strokeWidth="5" />
</div>
<div class="flex flex-row justify-center items-center">
<span class="text-2xl">{{ message }}</span>
</div>
</div>
</template>
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'
const ProgressSpinner = defineAsyncComponent(() => import('primevue/progressspinner'))
defineProps({
loading: {
type: Boolean,
default: false
},
message: {
type: String,
default: 'Loading...'
}
})
</script>
<style scoped lang="scss">
.loader {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(9, 5, 5, 0.56);
z-index: 1000;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.text-2xl {
margin-top: 10px;
font-size: 24px;
font-weight: bold;
color: #ffffff;
}
}
</style>

View File

@@ -5,4 +5,5 @@ export const icons = {
upload: 'fa-thin fa-sharp fa-upload', upload: 'fa-thin fa-sharp fa-upload',
save: 'fa-thin fa-sharp fa-floppy-disk', save: 'fa-thin fa-sharp fa-floppy-disk',
delete: 'fa-thin fa-sharp fa-trash', delete: 'fa-thin fa-sharp fa-trash',
loading: 'fa-solid fa-sharp fa-cog fa-spin',
} }

View File

@@ -1,7 +1,8 @@
<template> <template>
<Card class="md:w-2/3 w-full"> <Card class="md:w-2/3 w-full">
<template #title> <template #title>
Add New Load <span v-if="route.params.id">Edit Load</span>
<span v-else>Add New Load</span>
</template> </template>
<template #content> <template #content>
<div class="grid grid-cols-1"> <div class="grid grid-cols-1">
@@ -66,7 +67,7 @@
COL COL
</div> </div>
<div class="w-full mt-3"> <div class="w-full mt-3">
<InputMask placeholder="0.000" v-model="load.col" mask="9.999" class="w-full" /> <InputMask :unmask="loading" :value="load.col" placeholder="0.000" v-model="load.col" mask="9.999" class="w-full" />
<Message v-if="v$.$dirty && v$.col.$invalid" :value="false" size="small" severity="error" <Message v-if="v$.$dirty && v$.col.$invalid" :value="false" size="small" severity="error"
variant="simple">COL Required variant="simple">COL Required
</Message> </Message>
@@ -74,15 +75,20 @@
<div class="w-full mt-5"> <div class="w-full mt-5">
<label>Picture</label> <label>Picture</label>
<Message v-if="v$.$dirty && !file" :value="false" size="small" severity="error" <Message v-if="v$.$dirty && (!route.params.id && !file)" :value="false" size="small" severity="error"
variant="simple">Picture Required variant="simple">Picture Required
</Message> </Message>
<div class="w-1/2">
<img v-if="pictureUrl && route.params.id && !loading" :src="pictureUrl" alt="picture" />
</div>
<FileUpload v-model="file" mode="basic" @select="fileSelected" customUpload /> <FileUpload v-model="file" mode="basic" @select="fileSelected" customUpload />
</div> </div>
</div> </div>
</template> </template>
<template #footer> <template #footer>
<Button label="Add" :icon="icons.add" @click="add" /> <Button v-if="!route.params.id" label="Add" :icon="icons.add" @click="add" />
<Button v-else label="Save" :icon="icons.edit" @click="add" />
<Button class="ml-3" severity="danger" v-if="route.params.id" label="Delete" :icon="icons.delete" @click="deleteLoad" />
</template> </template>
</Card> </Card>
@@ -103,6 +109,7 @@
</template> </template>
</Dialog> </Dialog>
<FullScreenLoader :loading="loading" />
</template> </template>
<script lang="ts"> <script lang="ts">
interface Select { interface Select {
@@ -121,13 +128,16 @@ import { defineAsyncComponent, onMounted, ref } from 'vue'
import { Primers } from '../../types/primers' import { Primers } from '../../types/primers'
import { Powder } from '../../types/powder' import { Powder } from '../../types/powder'
import axios from 'axios' import axios from 'axios'
import { Response } from '../../types/Response' import { Load, Response } from '../../types/Response'
import { icons } from '../../lib/icons.ts' import { icons } from '../../lib/icons.ts'
import { FileUploadSelectEvent } from 'primevue/fileupload' import { FileUploadSelectEvent } from 'primevue/fileupload'
import useVuelidate from '@vuelidate/core' import useVuelidate from '@vuelidate/core'
import { required } from '@vuelidate/validators' import { required } from '@vuelidate/validators'
import { useToast } from 'primevue/usetoast' import { useToast } from 'primevue/usetoast'
import router from '../../router' import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
const Card = defineAsyncComponent(() => import('primevue/card')) const Card = defineAsyncComponent(() => import('primevue/card'))
const Select = defineAsyncComponent(() => import('primevue/select')) const Select = defineAsyncComponent(() => import('primevue/select'))
@@ -138,6 +148,7 @@ const InputMask = defineAsyncComponent(() => import('primevue/inputmask'))
const FileUpload = defineAsyncComponent(() => import('primevue/fileupload')) const FileUpload = defineAsyncComponent(() => import('primevue/fileupload'))
const Dialog = defineAsyncComponent(() => import('primevue/dialog')) const Dialog = defineAsyncComponent(() => import('primevue/dialog'))
const Message = defineAsyncComponent(() => import('primevue/message')) const Message = defineAsyncComponent(() => import('primevue/message'))
const FullScreenLoader = defineAsyncComponent(() => import('../../components/FullScreenLoader.vue'))
const toast = useToast() const toast = useToast()
@@ -145,6 +156,7 @@ const bullets = ref<Select[]>([])
const primers = ref<Select[]>([]) const primers = ref<Select[]>([])
const powders = ref<Select[]>([]) const powders = ref<Select[]>([])
const cartridges = ref<Select[]>([]) const cartridges = ref<Select[]>([])
const loading = ref(false)
const cartridgeName = ref('') const cartridgeName = ref('')
const addCartridgeDialog = ref(false) const addCartridgeDialog = ref(false)
@@ -154,6 +166,12 @@ const fileSelected = (e: FileUploadSelectEvent) => {
file.value = e.files[0] file.value = e.files[0]
} }
const pictureUrl = ref<string | null>(null)
const calcUrl = () => {
const cache = new Date().getMilliseconds()
pictureUrl.value = import.meta.env.VITE_API + `/load/${route.params.id}/photo?cache=${cache}`
}
const load = ref({ const load = ref({
bullet: '', bullet: '',
cartridge: '', cartridge: '',
@@ -191,21 +209,18 @@ const fetchBullets = async () => {
bullets.value.push({ label: `${bullet.manufacturer.name} ${bullet.weight}gr ${bullet.name}`, value: bullet.id }) bullets.value.push({ label: `${bullet.manufacturer.name} ${bullet.weight}gr ${bullet.name}`, value: bullet.id })
}) })
} }
const fetchPrimers = async () => { const fetchPrimers = async () => {
const response = await axios.get<any, Response<Primers[]>>(`${import.meta.env.VITE_API}/primer`) const response = await axios.get<any, Response<Primers[]>>(`${import.meta.env.VITE_API}/primer`)
response.data.payload.forEach((primer: Primers) => { response.data.payload.forEach((primer: Primers) => {
primers.value.push({ label: `${primer.manufacturer.name} ${primer.name}`, value: primer.id }) primers.value.push({ label: `${primer.manufacturer.name} ${primer.name}`, value: primer.id })
}) })
} }
const fetchPowders = async () => { const fetchPowders = async () => {
const response = await axios.get<any, Response<Powder[]>>(`${import.meta.env.VITE_API}/powder`) const response = await axios.get<any, Response<Powder[]>>(`${import.meta.env.VITE_API}/powder`)
response.data.payload.forEach((powder: Powder) => { response.data.payload.forEach((powder: Powder) => {
powders.value.push({ label: `${powder.manufacturer.name} ${powder.name}`, value: powder.id }) powders.value.push({ label: `${powder.manufacturer.name} ${powder.name}`, value: powder.id })
}) })
} }
const fetchCartridges = async () => { const fetchCartridges = async () => {
cartridges.value = [] cartridges.value = []
@@ -214,7 +229,6 @@ const fetchCartridges = async () => {
cartridges.value.push({ label: `${cartridge.name}`, value: cartridge.id }) cartridges.value.push({ label: `${cartridge.name}`, value: cartridge.id })
}) })
} }
const addCartridgeName = async () => { const addCartridgeName = async () => {
if (cartridgeName.value === '') { if (cartridgeName.value === '') {
return return
@@ -237,11 +251,10 @@ const addCartridgeName = async () => {
cartridgeName.value = '' cartridgeName.value = ''
addCartridgeDialog.value = false addCartridgeDialog.value = false
} }
const add = async () => { const add = async () => {
v$.value.$touch() v$.value.$touch()
if (v$.value.$invalid || !file.value) { if (v$.value.$invalid || (!route.params.id && !file.value)) {
toast.add({ toast.add({
severity: 'error', severity: 'error',
summary: 'Error', summary: 'Error',
@@ -252,6 +265,12 @@ const add = async () => {
return return
} }
let id = ""
if (route.params.id) {
id = "/" + route.params.id.toString()
}
const formData = new FormData() const formData = new FormData()
formData.append('bullet_id', load.value.bullet) formData.append('bullet_id', load.value.bullet)
formData.append('cartridge_id', load.value.cartridge) formData.append('cartridge_id', load.value.cartridge)
@@ -259,22 +278,43 @@ const add = async () => {
formData.append('powder_gr', load.value.powderGrs.toString()) formData.append('powder_gr', load.value.powderGrs.toString())
formData.append('primer_id', load.value.primer) formData.append('primer_id', load.value.primer)
formData.append('col', load.value.col) formData.append('col', load.value.col)
if (file.value) {
formData.append('photo', file.value) formData.append('photo', file.value)
}
try { try {
const response = await axios.post<any, Response<string>>(`${import.meta.env.VITE_API}/load`, formData, { const response = await axios.post<any, Response<string>>(`${import.meta.env.VITE_API}/load${id}`, formData, {
headers: { headers: {
'Content-Type': 'multipart/form-data', 'Content-Type': 'multipart/form-data',
}, },
}) })
const message = route.params.id ? 'Load updated' : 'Load added'
toast.add({ toast.add({
severity: 'success', severity: 'success',
summary: 'Success', summary: 'Success',
detail: 'Load added', detail: message,
life: 3000, life: 3000,
}) })
if (route.params.id) {
load.value = {
bullet: '',
cartridge: '',
powder: '',
powderGrs: 0,
primer: '',
col: '',
}
file.value = null
v$.value.$reset()
await fetchLoad()
return
}
await router.push(`/loads/edit/${response.data.payload}`) await router.push(`/loads/edit/${response.data.payload}`)
} catch (error) { } catch (error) {
toast.add({ toast.add({
@@ -284,14 +324,85 @@ const add = async () => {
life: 3000, life: 3000,
}) })
} }
} }
const deleteLoad = async () => {
if (!route.params.id) {
return
}
try {
await axios.delete(`${import.meta.env.VITE_API}/load/${route.params.id}`)
toast.add({
severity: 'success',
summary: 'Success',
detail: 'Load deleted',
life: 3000,
})
await router.push('/loads/search')
} catch (error) {
toast.add({
severity: 'error',
summary: 'Error',
detail: 'Error deleting load',
life: 3000,
})
}
}
const fetchLoad = async () => {
if (!route.params.id) {
return
}
loading.value = true
const response = await axios.get<any, Response<Load>>(`${import.meta.env.VITE_API}/load/${route.params.id}`)
if (response.data.payload) {
load.value.cartridge = response.data.payload.cartridge_id
load.value.bullet = response.data.payload.bullet.id
load.value.powder = response.data.payload.powder.id
load.value.powderGrs = response.data.payload.powder_gr
load.value.primer = response.data.payload.primer.id
load.value.col = response.data.payload.col.toString()
if (!load.value.col.includes('.')) {
load.value.col = `${load.value.col}.000`
} else {
const parts = load.value.col.split('.')
if (parts[1].length < 3) {
load.value.col = `${parts[0]}.${parts[1].padEnd(3, '0')}`
}
}
calcUrl()
} else {
toast.add({
severity: 'error',
summary: 'Error',
detail: 'Load not found',
life: 3000,
})
await router.push('/loads')
}
loading.value = false
}
onMounted(() => { onMounted(() => {
fetchBullets() fetchBullets()
fetchPrimers() fetchPrimers()
fetchPowders() fetchPowders()
fetchCartridges() fetchCartridges()
if (route.params.id) {
setTimeout(() => {
fetchLoad()
}, 100)
}
}) })
</script> </script>

View File

@@ -8,13 +8,15 @@
:value="loads" :value="loads"
filterDisplay="row" filterDisplay="row"
paginator paginator
:rowsPerPageOptions="[5, 10, 20, 50]"
size="small" size="small"
:sortField="sortField" :sortField="sortField"
:sortOrder="sortOrder" :sortOrder="sortOrder"
@update:sortField="(e: string) => {sortField = e; fetchLoads()}" @update:sortField="(e: string) => {sortField = e; fetchLoads()}"
@update:sortOrder="(e: number | undefined) => {sortOrder = e; fetchLoads()}" @update:sortOrder="(e: number | undefined) => {sortOrder = e; fetchLoads()}"
@page="updatePagination"
:rows="rowsPerPage"
lazy lazy
:rows="50"
:totalRecords="total" :totalRecords="total"
:loading="loading" :loading="loading"
> >
@@ -42,7 +44,9 @@
@change="fetchLoads" /> @change="fetchLoads" />
</template> </template>
<template #body="{ data }"> <template #body="{ data }">
<a target="_blank" :href="data.bullet.manufacturer.url">
{{ data.bullet.manufacturer.name }} {{ data.bullet.manufacturer.name }}
</a>
</template> </template>
</Column> </Column>
<Column field="bullet_name" header="Bullet" :sortable="true" :showFilterMenu="false"> <Column field="bullet_name" header="Bullet" :sortable="true" :showFilterMenu="false">
@@ -63,7 +67,9 @@
@change="fetchLoads" /> @change="fetchLoads" />
</template> </template>
<template #body="{ data }"> <template #body="{ data }">
<a target="_blank" :href="data.primer.manufacturer.url">
{{ data.primer.manufacturer.name }} {{ data.primer.manufacturer.name }}
</a>
</template> </template>
</Column> </Column>
<Column field="primer_name" header="Primer" :sortable="true" :showFilterMenu="false"> <Column field="primer_name" header="Primer" :sortable="true" :showFilterMenu="false">
@@ -83,7 +89,9 @@
@change="fetchLoads" /> @change="fetchLoads" />
</template> </template>
<template #body="{ data }"> <template #body="{ data }">
<a target="_blank" :href="data.powder.manufacturer.url">
{{ data.powder.manufacturer.name }} {{ data.powder.manufacturer.name }}
</a>
</template> </template>
</Column> </Column>
@@ -104,8 +112,13 @@
</Column> </Column>
<Column field="edit" header="Edit"> <Column field="edit" header="Edit">
<template #body> <template #body="{ data }">
<Button size="small" text :icon="icons.edit" /> <Button
size="small"
text
:icon="icons.edit"
@click="router.push('/loads/edit/' + data.id)"
/>
</template> </template>
</Column> </Column>
</DataTable> </DataTable>
@@ -116,22 +129,13 @@
import { Bullet } from '../../types/bullet' import { Bullet } from '../../types/bullet'
import { Powder } from '../../types/powder' import { Powder } from '../../types/powder'
import { Primers } from '../../types/primers' import { Primers } from '../../types/primers'
import { Load } from '../../types/Response'
interface LoadResponse { interface LoadResponse {
total: number total: number
results: Load[] results: Load[]
} }
interface Load {
id: string
bullet: Bullet
cartridge: string
powder: Powder
powder_gr: number
primer: Primers
col: number
}
interface Option { interface Option {
label: string label: string
value: string value: string
@@ -143,6 +147,7 @@ import { Response } from '../../types/Response'
import axios from 'axios' import axios from 'axios'
import Column from 'primevue/column' import Column from 'primevue/column'
import { icons } from '../../lib/icons.ts' import { icons } from '../../lib/icons.ts'
import router from '../../router'
const DataTable = defineAsyncComponent(() => import('primevue/datatable')) const DataTable = defineAsyncComponent(() => import('primevue/datatable'))
const Card = defineAsyncComponent(() => import('primevue/card')) const Card = defineAsyncComponent(() => import('primevue/card'))
@@ -151,6 +156,8 @@ const MultiSelect = defineAsyncComponent(() => import('primevue/multiselect'))
const loads = ref<Load[]>([]) const loads = ref<Load[]>([])
const total = ref(0) const total = ref(0)
const rowsPerPage = ref(50)
const page = ref(1)
const loading = ref(true) const loading = ref(true)
// use local storage to store the selected filters // use local storage to store the selected filters
@@ -181,6 +188,14 @@ const powderManufacturerSelected = ref<string[]>(localStorageFilters.powderManuf
const powderOptions = ref<Option[]>([]) const powderOptions = ref<Option[]>([])
const powderSelected = ref<string[]>(localStorageFilters.powderSelected ?? []) const powderSelected = ref<string[]>(localStorageFilters.powderSelected ?? [])
const updatePagination = (e: { page: number, rows: number }) => {
console.log(e)
page.value = e.page + 1
rowsPerPage.value = e.rows
fetchLoads()
}
const fetchLoads = async () => { const fetchLoads = async () => {
loading.value = true loading.value = true
@@ -220,6 +235,9 @@ const fetchLoads = async () => {
searchParams.unshift(`powder_id=${powderSelected.value.join(',')}`) searchParams.unshift(`powder_id=${powderSelected.value.join(',')}`)
} }
searchParams.unshift(`limit=${rowsPerPage.value}`)
searchParams.unshift(`page=${page.value}`)
localStorage.setItem(localStorageKey, JSON.stringify({ localStorage.setItem(localStorageKey, JSON.stringify({
cartridgeSelected: cartridgeSelected.value, cartridgeSelected: cartridgeSelected.value,
bulletManufacturerSelected: bulletManufacturerSelected.value, bulletManufacturerSelected: bulletManufacturerSelected.value,
@@ -257,6 +275,11 @@ onMounted(() => {
value: bullet.manufacturer.id, value: bullet.manufacturer.id,
})) }))
// dedupe the bullet Manufacturer options
bulletManufacturerOptions.value = bulletManufacturerOptions.value.filter((option, index, self) =>
index === self.findIndex((o) => o.value === option.value)
)
bulletOptions.value = resp.data.payload.map((bullet) => ({ bulletOptions.value = resp.data.payload.map((bullet) => ({
label: `${bullet.name} ${bullet.weight}gr .${bullet.diameter}`, label: `${bullet.name} ${bullet.weight}gr .${bullet.diameter}`,
value: bullet.id, value: bullet.id,
@@ -269,6 +292,11 @@ onMounted(() => {
value: primer.manufacturer.id, value: primer.manufacturer.id,
})) }))
// dedupe the primer Manufacturer options
primerManufacturerOptions.value = primerManufacturerOptions.value.filter((option, index, self) =>
index === self.findIndex((o) => o.value === option.value)
)
primerOptions.value = resp.data.payload.map((primer) => ({ primerOptions.value = resp.data.payload.map((primer) => ({
label: primer.name, label: primer.name,
value: primer.id, value: primer.id,
@@ -281,6 +309,11 @@ onMounted(() => {
value: powder.manufacturer.id, value: powder.manufacturer.id,
})) }))
// dedupe the powder Manufacturer options
powderManufacturerOptions.value = powderManufacturerOptions.value.filter((option, index, self) =>
index === self.findIndex((o) => o.value === option.value)
)
powderOptions.value = resp.data.payload.map((powder) => ({ powderOptions.value = resp.data.payload.map((powder) => ({
label: powder.name, label: powder.name,
value: powder.id, value: powder.id,

View File

@@ -61,6 +61,10 @@ const routes = [
path: '/loads/search', path: '/loads/search',
component: () => import('../pages/loads/Search.vue'), component: () => import('../pages/loads/Search.vue'),
}, },
{
path: '/loads/edit/:id',
component: () => import('../pages/loads/Add.vue'),
},
] as RouteRecordRaw[] ] as RouteRecordRaw[]
const router = createRouter({ const router = createRouter({

View File

@@ -1,4 +1,18 @@
import {AxiosResponse} from "axios"; import {AxiosResponse} from "axios";
import { Bullet } from './bullet'
import { Powder } from './powder'
import { Primers } from './primers'
interface Load {
id: string
bullet: Bullet
cartridge: string
cartridge_id: string
powder: Powder
powder_gr: number
primer: Primers
col: number
}
export interface Response<T> extends AxiosResponse { export interface Response<T> extends AxiosResponse {
data: { data: {