From b40f37c95938c00f44bb7d899dfacc102309e2c4 Mon Sep 17 00:00:00 2001 From: hizumi Date: Sun, 30 Nov 2025 18:18:36 -0600 Subject: [PATCH 1/2] cerate deployment configuration add continuous deployment yaml to execute on every push to main to build and make live --- .gitea/workflows/cd-deploy.yaml | 62 +++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .gitea/workflows/cd-deploy.yaml diff --git a/.gitea/workflows/cd-deploy.yaml b/.gitea/workflows/cd-deploy.yaml new file mode 100644 index 0000000..66e64f1 --- /dev/null +++ b/.gitea/workflows/cd-deploy.yaml @@ -0,0 +1,62 @@ +name: Continuous Deployment +on: + push: + +jobs: + Deploy: + name: Update Deployment + runs-on: ubuntu-latest + container: + volumes: + - /var/www/html/milsim-site-v4:/var/www/html/milsim-site-v4:rw + steps: + - name: Setup Local Environment + run: | + groupadd -g 989 nginx || true + useradd nginx -u 990 -g nginx -m || true + + - name: Verify Node Environment + run: | + npm -v + node -v + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: 'main' + + - name: Token Copy + run: | + cd /var/www/html/milsim-site-v4 + cp /workspace/17th-Ranger-Battalion-ORG/milsim-site-v4/.git/config .git/config + chown nginx:nginx .git/config + + - name: Fix File Permissions + run: | + sudo chown -R nginx:nginx /var/www/html/milsim-site-v4 + sudo chmod -R u+w /var/www/html/milsim-site-v4 + + - name: Update Application Code + run: | + sudo -u nginx bash -c "cd /var/www/html/milsim-site-v4 && git reset --hard && git pull origin main" + + - name: Update Shared Dependencies + run: | + sudo -u nginx bash -c "cd /var/www/html/milsim-site-v4/shared && npm install" + + - name: Update UI Dependencies + run: | + sudo -u nginx bash -c "cd /var/www/html/milsim-site-v4/ui && npm install" + + - name: Update API Dependencies + run: | + sudo -u nginx bash -c "cd /var/www/html/milsim-site-v4/api && npm install" + + - name: Build UI + run: | + sudo -u nginx bash -c "cd /var/www/html/milsim-site-v4/ui && npm run build" + + - name: Build API + run: | + sudo -u nginx bash -c "cd /var/www/html/milsim-site-v4/api && npm run build" From 41cdd0b74f20420fb244a0a16b5c0b1a5b27d0c1 Mon Sep 17 00:00:00 2001 From: ajdj100 Date: Wed, 3 Dec 2025 00:55:53 -0500 Subject: [PATCH 2/2] Added more strict form validation rules with user feedback --- shared/schemas/trainingReportSchema.ts | 41 ++++++++++++++++++- .../trainingReport/trainingReportForm.vue | 15 ++++++- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/shared/schemas/trainingReportSchema.ts b/shared/schemas/trainingReportSchema.ts index 5bfb1fd..7dd7baa 100644 --- a/shared/schemas/trainingReportSchema.ts +++ b/shared/schemas/trainingReportSchema.ts @@ -1,11 +1,11 @@ import { z } from "zod"; export const courseEventAttendeeSchema = z.object({ - attendee_id: z.number({invalid_type_error: "Must select a member"}).int().positive(), + attendee_id: z.number({ invalid_type_error: "Must select a member" }).int().positive(), passed_bookwork: z.boolean(), passed_qual: z.boolean(), remarks: z.string(), - attendee_role_id: z.number({invalid_type_error: "Must select a role"}).int().positive() + attendee_role_id: z.number({ invalid_type_error: "Must select a role" }).int().positive() }) export const trainingReportSchema = z.object({ @@ -19,5 +19,42 @@ export const trainingReportSchema = z.object({ ), remarks: z.string().nullable().optional(), attendees: z.array(courseEventAttendeeSchema).default([]), +}).superRefine((data, ctx) => { + const trainerRole = 1; + const traineeRole = 2; + + const hasTrainer = data.attendees.some((a) => a.attendee_role_id === trainerRole); + const hasTrainee = data.attendees.some((a) => a.attendee_role_id === traineeRole); + + if (!hasTrainer) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["attendees"], + message: "At least one Primary Trainer is required.", + }); + } + + if (!hasTrainee) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["attendees"], + message: "At least one Trainee is required.", + }); + } + + //no duplicates + const idCounts = new Map(); + + data.attendees.forEach((a, index) => { + idCounts.set(a.attendee_id, (idCounts.get(a.attendee_id) ?? 0) + 1); + + if (idCounts.get(a.attendee_id)! > 1) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["attendees"], + message: "Cannot have duplicate attendee.", + }); + } + }) }) diff --git a/ui/src/components/trainingReport/trainingReportForm.vue b/ui/src/components/trainingReport/trainingReportForm.vue index 79b7933..26ef3c1 100644 --- a/ui/src/components/trainingReport/trainingReportForm.vue +++ b/ui/src/components/trainingReport/trainingReportForm.vue @@ -18,10 +18,12 @@ import FieldSet from '../ui/field/FieldSet.vue' import FieldLegend from '../ui/field/FieldLegend.vue' import FieldDescription from '../ui/field/FieldDescription.vue' import Checkbox from '../ui/checkbox/Checkbox.vue' +import { configure } from 'vee-validate' const { handleSubmit, resetForm, errors, values, setFieldValue } = useForm({ validationSchema: toTypedSchema(trainingReportSchema), + validateOnMount: false, initialValues: { course_id: null, event_date: "", @@ -129,8 +131,17 @@ onMounted(async () => {
- Attendees - Add members who attended this session. +
+ Attendees + Add members who attended this session. +
+
+ {{ errors.attendees }} +
+
+
+