41 Commits

Author SHA1 Message Date
8ddac9a56d 🚀 Update push command in CI workflow for release branch
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m40s
🧪 ✨ Unit Tests Workflow / 🧪 🐹 GolangCI-Lint (push) Successful in 1m43s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 3m30s
Modified the push command in the CI workflow to correctly target the release branch for deployment. This ensures that changes are pushed to the appropriate branch, enhancing the deployment process.
2026-02-06 20:42:46 -05:00
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
343abbb801 Actual final build before release
Some checks failed
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Failing after 2m42s
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Failing after 2m47s
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 18m37s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 20m14s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Failing after 54s
2025-05-16 14:02:19 -04:00
13aad5254e Feed. You. Stuff. No time. (#6)
Some checks failed
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m16s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 3m53s
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 5m9s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 6m9s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Failing after 9s
Reviewed-on: Siteworxpro/reloading-manager#6
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
2025-05-16 11:20:41 -04:00
aeba95dc41 [create-pull-request] automated change (#5)
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m15s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 3m14s
Co-authored-by: rrise <+rrise@users.noreply.github.com>
Reviewed-on: Siteworxpro/reloading-manager#5
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
2025-05-16 11:13:40 -04:00
b40edf70d4 and a comma (#4)
Some checks failed
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 2m50s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Failing after 2m45s
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m16s
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 5m25s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 6m23s
Reviewed-on: Siteworxpro/reloading-manager#4
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
2025-05-16 10:21:03 -04:00
4f750ae15c [create-pull-request] automated change (#3)
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 8m6s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 10m49s
Co-authored-by: rrise <+rrise@users.noreply.github.com>
Reviewed-on: Siteworxpro/reloading-manager#3
Co-authored-by: Ron Rise <ron@siteworxpro.com>
Co-committed-by: Ron Rise <ron@siteworxpro.com>
2025-05-16 10:08:55 -04:00
3246450d77 Merge pull request 'This is not the commit message you are looking for' (#2) from deployments into master
Some checks failed
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 5m47s
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m15s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 6m16s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Failing after 49s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 3m11s
Reviewed-on: Siteworxpro/reloading-manager#2
2025-05-16 09:47:00 -04:00
74681e01b3 This is not the commit message you are looking for
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m23s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 3m0s
2025-05-16 09:42:39 -04:00
9dce6b8930 various changes
Some checks failed
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 6m36s
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 7m45s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Failing after 52s
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 3m14s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 5m22s
2025-05-16 09:19:02 -04:00
7c02aa7148 Merge pull request '📝🔄 Update deployment manifest with new image tags' (#1) from release/v0.0.29-deploy into master
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 4m48s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 8m1s
Reviewed-on: Siteworxpro/reloading-manager#1
2025-05-16 09:09:05 -04:00
GitHub Action 🤖
a8c470a474 📝🔄 Update deployment manifest with new image tags 2025-05-16 13:01:57 +00:00
95b626b439 It's Working!
All checks were successful
🏗️ ✨ Build Workflow / 🖥️ 🔨 Build Backend (push) Successful in 7m3s
🏗️ ✨ Build Workflow / 🚀 ✨ Deploy Application (push) Successful in 57s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 5m7s
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 1m17s
🏗️ ✨ Build Workflow / 🖼️ 🔨 Build Frontend (push) Successful in 5m35s
2025-05-16 08:50:55 -04:00
b9a6598e87 Fucking templates.
All checks were successful
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Successful in 2m24s
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Successful in 5m18s
2025-05-16 08:45:01 -04:00
4251a03139 That last commit was cringe
Some checks failed
🧪 ✨ Unit Tests Workflow / 🔍 🐹 Go Tests (push) Has been cancelled
🧪 ✨ Unit Tests Workflow / 🧪 📜 JavaScript Tests (push) Has been cancelled
2025-05-16 08:44:02 -04:00
691a32ff56 Just committing so I can go home
All checks were successful
🧪✨ Unit Tests Workflow / 🔍🐹 Go Tests (push) Successful in 8m21s
🧪✨ Unit Tests Workflow / 🧪📜 JavaScript Tests (push) Successful in 1m8s
2025-05-16 08:29:57 -04:00
3631a4b5dc ci test 2025-04-21 18:39:16 -04:00
edbd5b4f49 I would rather be playing Destiny 2. 2025-04-21 18:35:37 -04:00
a20bef65ae should work now. 2025-04-21 18:34:38 -04:00
4056e6705d Merge branch 'update-deployment-v0.0.28' into 'master'
Update deployment manifest with new image tags

See merge request rrise/reloading-manager!2
2025-04-21 22:34:01 +00:00
fc4305f161 yo recipes 2025-04-21 18:32:09 -04:00
f0fc8b7707 Update deployment manifest with new image tags 2025-04-21 22:29:48 +00:00
409da15ff5 lol digg 2025-04-21 18:25:21 -04:00
74cb8b0bc3 Merge branch 'update-deployment-v0.0.27' into 'master'
Update deployment manifest with new image tags

See merge request rrise/reloading-manager!1
2025-04-21 22:16:15 +00:00
f8fda1f749 Update deployment manifest with new image tags 2025-04-21 21:26:25 +00:00
32 changed files with 991 additions and 357 deletions

View File

@@ -1,44 +1,37 @@
on: on:
push: push:
tags: tags:
- '**' - 'v*'
name: 🏗️✨ Build Workflow name: 🏗️ ✨ Build Workflow
jobs: jobs:
BuildFrontend: BuildFrontend:
name: 🖼️🔨 Build Frontend name: 🖼️ 🔨 Build Frontend
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 📖 🔍 Checkout Repository Code
- 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 uses: actions/checkout@v2
with: with:
fetch-depth: 1 fetch-depth: 1
- name: 🔑🔐 Login to Docker Hub - name: 🔑 🔐 Login to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
username: ${{ vars.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: 🔑🛠️ Login to Siteworx Registry - name: 🔑 🛠️ Login to Siteworx Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
username: ${{ vars.SITEWORX_USERNAME }} username: ${{ secrets.SITEWORX_USERNAME }}
password: ${{ secrets.SITEWORX_PASSWORD }} password: ${{ secrets.SITEWORX_PASSWORD }}
registry: scr.siteworxpro.com registry: scr.siteworxpro.com
- name: 🏗️🔧 Set up Docker Buildx - name: 🏗️ 🔧 Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: 🐳🔨 Build Frontend Container - name: 🐳 🔨 Build Frontend Container
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
build-args: | build-args: |
@@ -48,7 +41,7 @@ jobs:
tags: scr.siteworxpro.com/reloading-manager/frontend:${{ gitea.ref_name }} tags: scr.siteworxpro.com/reloading-manager/frontend:${{ gitea.ref_name }}
push: true push: true
- name: 📦✨ Build Latest Frontend Container - name: 📦 ✨ Build Latest Frontend Container
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
build-args: | build-args: |
@@ -59,38 +52,31 @@ jobs:
push: true push: true
BuildBackend: BuildBackend:
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:
fetch-depth: 1 fetch-depth: 1
- name: 🔑🔐 Login to Docker Hub - name: 🔑 🔐 Login to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
username: ${{ vars.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: 🔑🛠️ Login to Siteworx Registry - name: 🔑 🛠️ Login to Siteworx Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
username: ${{ vars.SITEWORX_USERNAME }} username: ${{ secrets.SITEWORX_USERNAME }}
password: ${{ secrets.SITEWORX_PASSWORD }} password: ${{ secrets.SITEWORX_PASSWORD }}
registry: scr.siteworxpro.com registry: scr.siteworxpro.com
- name: 🏗️🔧 Set up Docker Buildx - name: 🏗️ 🔧 Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: 🐳🔨 Build Backend Container - name: 🐳 🔨 Build Backend Container
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: ./backend context: ./backend
@@ -98,7 +84,7 @@ jobs:
tags: scr.siteworxpro.com/reloading-manager/backend:${{ gitea.ref_name }} tags: scr.siteworxpro.com/reloading-manager/backend:${{ gitea.ref_name }}
push: true push: true
- name: 📦✨ Build Latest Backend Container - name: 📦 ✨ Build Latest Backend Container
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: ./backend context: ./backend
@@ -107,36 +93,50 @@ jobs:
push: true push: true
Deploy: Deploy:
name: 🚀✨ Deploy Application name: 🚀 ✨ Deploy Application
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [BuildFrontend, BuildBackend] needs: [BuildFrontend, BuildBackend]
steps: steps:
- name: 📖 🔍 Checkout Repository Code
- 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 uses: actions/checkout@v2
with: with:
fetch-depth: 1 fetch-depth: 1
- name: 📝🔧 Update Deployment Manifest - name: 📝 🔧 Update Deployment Manifest
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 release/${{ gitea.ref_name }} -o ci.skip || echo "No changes to push"
- name: 🚀✨ Create Pull Request - name: 🚀 ✨ Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v7 uses: peter-evans/create-pull-request@v7
env:
NODE_TLS_REJECT_UNAUTHORIZED: 0
with:
base: master
add-paths: argocd/deployment/deployment.yml
title: "🚀 ✨ Release ${GITHUB_REF_NAME} - Deploy"
branch: release/${{ gitea.ref_name }}-deploy
committer: "Gitea Action 🤖 <gitia@siteworxpro.com>"
body: "📝 🔄 Update deployment manifest with new image tags for release ${{ gitea.ref_name }}"

View File

@@ -1,63 +1,94 @@
on: on:
workflow_dispatch:
inputs:
test:
description: 'Run tests'
required: true
default: 'true'
push: push:
paths-ignore:
- argocd/**/*
branches: branches:
- "*" - "*"
name: 🧪✨ Unit Tests Workflow name: 🧪 ✨ Unit Tests Workflow
jobs: jobs:
build-javascript: build-javascript:
name: 🧪📜 JavaScript Tests name: 🧪 📜 JavaScript Tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 🛡️🔒 Add Siteworx CA Certificates - name: 🛡️ 🔒 Add Siteworx CA Certificates
run: | run: |
apt update && apt install -yq ca-certificates curl 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 curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates update-ca-certificates
- name: 📖🔍 Checkout Repository Code - name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
fetch-depth: 1 fetch-depth: 1
- name: ⚙️🔧 Set up Node.js Environment - name: ⚙️ 🔧 Set up Node.js Environment
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: '22.14.0' node-version: '22.14.0'
- name: 📦📥 Install Dependencies - name: 📦 📥 Install Dependencies
run: | run: |
cd frontend cd frontend
npm install npm install
- name: ✅🧪 Run JavaScript Tests - name: 🧪 Run JavaScript Tests
run: | run: |
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'
GOPROXY: 'direct' GOPROXY: 'direct'
name: 🔍🐹 Go Tests name: 🔍 🐹 Go Tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 🛡️🔒 Add Siteworx CA Certificates - name: 🛡️ 🔒 Add Siteworx CA Certificates
run: | run: |
apt update && apt install -yq ca-certificates curl 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 curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates update-ca-certificates
- 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.0' 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
with: with:
fetch-depth: 1 fetch-depth: 1
- name: 📦📥 Install Dependencies - name: 📦 📥 Install Dependencies
run: | run: |
cd backend cd backend
go mod download go mod download
- name: ✅🔍 Run Go Tests - name: 🔍 Run Go Tests
run: | run: |
cd backend cd backend
go test -v ./... -coverprofile=coverage.out go test -v ./... -coverprofile=coverage.out

View File

@@ -4,12 +4,16 @@ stages:
- Update Deployment - Update Deployment
- Create Commit - Create Commit
- Create Merge Request - Create Merge Request
- Trigger
NodeJs Tests: NodeJs Tests:
stage: Tests stage: Tests
image: node:22.14.0 image: node:22.14.0
except: rules:
- tags - if: '$CI_PIPELINE_SOURCE == "push"'
changes:
- frontend/**
- frontend/.gitlab-ci.yml
before_script: before_script:
- cd frontend - cd frontend
- npm install - npm install
@@ -20,6 +24,11 @@ include:
- project: 'shared/blueprints' - project: 'shared/blueprints'
file: 'jobs/golang-tests.yml' file: 'jobs/golang-tests.yml'
ref: master ref: master
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
changes:
- backend/**
- backend/.gitlab-ci.yml
inputs: inputs:
job_name: "Go Tests" job_name: "Go Tests"
working_directory: "backend" working_directory: "backend"
@@ -61,6 +70,18 @@ include:
context: "frontend" context: "frontend"
dockerfile: "frontend/Dockerfile" dockerfile: "frontend/Dockerfile"
- project: 'shared/blueprints'
file: 'jobs/trigger-argocd.yml'
ref: master
rules:
- changes:
- argocd/**/*
inputs:
stage: Trigger
argocdServer: ${ARGOCD_SERVER}
argocdAuthToken: ${ARGOCD_AUTH_TOKEN}
argocdAppName: ${ARGOCD_APP_NAME}
Update Deployment: Update Deployment:
image: siteworxpro/alpine:3.21.3 image: siteworxpro/alpine:3.21.3
rules: rules:
@@ -84,7 +105,7 @@ Create Commit:
- Update Deployment - Update Deployment
image: siteworxpro/git:2.49.0 image: siteworxpro/git:2.49.0
before_script: | before_script: |
git config --global user.name "${GITLAB_USER_NAME}" git config --global user.name "${GITLAB_USER_NAME} via Gitlab Runner"
git config --global user.email "${GITLAB_USER_EMAIL}" git config --global user.email "${GITLAB_USER_EMAIL}"
script: | script: |
git pull origin master git pull origin master
@@ -107,7 +128,8 @@ Create Merge Request:
curl --request POST --header "PRIVATE-TOKEN: glpat-hv-uxCx3PDNKn7ihyXce" \ curl --request POST --header "PRIVATE-TOKEN: glpat-hv-uxCx3PDNKn7ihyXce" \
--data "source_branch=update-deployment-${CI_COMMIT_TAG}" \ --data "source_branch=update-deployment-${CI_COMMIT_TAG}" \
--data "target_branch=master" \ --data "target_branch=master" \
--data "title=Update deployment manifest with new image tags" \ --data "title=Update deployment manifest for version ${CI_COMMIT_TAG}" \
--data "description=This merge request updates the deployment manifest with the new image tags." \ --data "description=This merge request updates the deployment manifest with the new image tags." \
--data "remove_source_branch=true" \ --data "remove_source_branch=true" \
--data "squash_commits=true" \
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests"

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.26 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.26 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.0 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.0 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: {