diff --git a/compose.yaml b/compose.yaml index 8752859..8b4e844 100644 --- a/compose.yaml +++ b/compose.yaml @@ -30,19 +30,35 @@ services: - DB_NAME=${DB_DATABASE} - GIN_MODE=${GIN_MODE} ports: - - "8089:8080" + - "34013:8080" depends_on: db: condition: service_healthy networks: - wagfarm-net healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8080/health"] # or use the health endpoint of your API + test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 start_period: 5s - + + ui: + build: ./wagfarm-ui + container_name: wagfarm-ui + restart: always + ports: + - "34014:80" + depends_on: + api: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:80"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + networks: wagfarm-net: diff --git a/wagfarm-api/Dockerfile b/wagfarm-api/Dockerfile index 7119699..25b36c4 100644 --- a/wagfarm-api/Dockerfile +++ b/wagfarm-api/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Build the Go binary -FROM golang:1.21-alpine AS builder +FROM golang:1.24-alpine AS builder WORKDIR /app @@ -16,6 +16,8 @@ RUN go build -o wagfarm-api main.go # Stage 2: Minimal runtime image FROM alpine:latest +RUN apk add curl + WORKDIR /root/ # Copy the binary from the builder diff --git a/wagfarm-api/endpoints.txt b/wagfarm-api/endpoints.txt new file mode 100644 index 0000000..9b4f4e7 --- /dev/null +++ b/wagfarm-api/endpoints.txt @@ -0,0 +1,131 @@ +GET /v1/assets/fertilizer/ +GET /v1/assets/fertilizer/:id +POST /v1/assets/fertilizer/ +PUT /v1/assets/fertilizer/:id +DELETE /v1/assets/fertilizer/:id + +GET /v1/assets/land/ +GET /v1/assets/land/:id +POST /v1/assets/land/ +PUT /v1/assets/land/:id +DELETE /v1/assets/land/:id + +GET /v1/assets/machine/ +GET /v1/assets/machine/:id +POST /v1/assets/machine/ +PUT /v1/assets/machine/:id +DELETE /v1/assets/machine/:id + +GET /v1/assets/pesticide/ +GET /v1/assets/pesticide/:id +POST /v1/assets/pesticide/ +PUT /v1/assets/pesticide/:id +DELETE /v1/assets/pesticide/:id + +GET /v1/assets/plant/ +GET /v1/assets/plant/:id +POST /v1/assets/plant/ +PUT /v1/assets/plant/:id +DELETE /v1/assets/plant/:id + +GET /v1/assets/product/ +GET /v1/assets/product/:id +POST /v1/assets/product/ +PUT /v1/assets/product/:id +DELETE /v1/assets/product/:id + +GET /v1/assets/seed/ +GET /v1/assets/seed/:id +POST /v1/assets/seed/ +PUT /v1/assets/seed/:id +DELETE /v1/assets/seed/:id + +GET /v1/logs/ +GET /v1/logs/:id +POST /v1/logs/ +PUT /v1/logs/:id +DELETE /v1/logs/:id + +GET /v1/logs/cropprotection/ +GET /v1/logs/cropprotection/:id +POST /v1/logs/cropprotection/ +PUT /v1/logs/cropprotection/:id +DELETE /v1/logs/cropprotection/:id + +GET /v1/logs/fertilizer/ +GET /v1/logs/fertilizer/:id +POST /v1/logs/fertilizer/ +PUT /v1/logs/fertilizer/:id +DELETE /v1/logs/fertilizer/:id + +GET /v1/logs/harvest/ +GET /v1/logs/harvest/:id +POST /v1/logs/harvest/ +PUT /v1/logs/harvest/:id +DELETE /v1/logs/harvest/:id + +GET /v1/logs/seeding/ +GET /v1/logs/seeding/:id +POST /v1/logs/seeding/ +PUT /v1/logs/seeding/:id +DELETE /v1/logs/seeding/:id + +GET /v1/taxonomy/crop/ +GET /v1/taxonomy/crop/:id +POST /v1/taxonomy/crop/ +PUT /v1/taxonomy/crop/:id +DELETE /v1/taxonomy/crop/:id + +GET /v1/taxonomy/customer/ +GET /v1/taxonomy/customer/:id +POST /v1/taxonomy/customer/ +PUT /v1/taxonomy/customer/:id +DELETE /v1/taxonomy/customer/:id + +GET /v1/taxonomy/fertilizertype/ +GET /v1/taxonomy/fertilizertype/:id +POST /v1/taxonomy/fertilizertype/ +PUT /v1/taxonomy/fertilizertype/:id +DELETE /v1/taxonomy/fertilizertype/:id + +GET /v1/taxonomy/ingredient/ +GET /v1/taxonomy/ingredient/:id +POST /v1/taxonomy/ingredient/ +PUT /v1/taxonomy/ingredient/:id +DELETE /v1/taxonomy/ingredient/:id + +GET /v1/taxonomy/pesticidetype/ +GET /v1/taxonomy/pesticidetype/:id +POST /v1/taxonomy/pesticidetype/ +PUT /v1/taxonomy/pesticidetype/:id +DELETE /v1/taxonomy/pesticidetype/:id + +GET /v1/taxonomy/producttype/ +GET /v1/taxonomy/producttype/:id +POST /v1/taxonomy/producttype/ +PUT /v1/taxonomy/producttype/:id +DELETE /v1/taxonomy/producttype/:id + +GET /v1/taxonomy/seedingcondition/ +GET /v1/taxonomy/seedingcondition/:id +POST /v1/taxonomy/seedingcondition/ +PUT /v1/taxonomy/seedingcondition/:id +DELETE /v1/taxonomy/seedingcondition/:id + +GET /v1/taxonomy/seedingtechnique/ +GET /v1/taxonomy/seedingtechnique/:id +POST /v1/taxonomy/seedingtechnique/ +PUT /v1/taxonomy/seedingtechnique/:id +DELETE /v1/taxonomy/seedingtechnique/:id + +GET /v1/taxonomy/seedtype/ +GET /v1/taxonomy/seedtype/:id +POST /v1/taxonomy/seedtype/ +PUT /v1/taxonomy/seedtype/:id +DELETE /v1/taxonomy/seedtype/:id + +GET /v1/taxonomy/seller/ +GET /v1/taxonomy/seller/:id +POST /v1/taxonomy/seller/ +PUT /v1/taxonomy/seller/:id +DELETE /v1/taxonomy/seller/:id diff --git a/wagfarm-api/go.mod b/wagfarm-api/go.mod index e539864..1be6bc1 100644 --- a/wagfarm-api/go.mod +++ b/wagfarm-api/go.mod @@ -1,6 +1,6 @@ module wagfarm-api -go 1.20 +go 1.24.2 require ( github.com/gin-gonic/gin v1.10.0 @@ -19,8 +19,8 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.20.0 // indirect - github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.5.5 // indirect @@ -29,19 +29,22 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/stretchr/testify v1.10.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/crypto v0.37.0 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/sync v0.13.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/text v0.24.0 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/wagfarm-api/go.sum b/wagfarm-api/go.sum index dd803ec..303eac7 100644 --- a/wagfarm-api/go.sum +++ b/wagfarm-api/go.sum @@ -6,7 +6,9 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= @@ -14,16 +16,18 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= @@ -43,6 +47,10 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= @@ -54,7 +62,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -68,6 +81,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -75,33 +90,28 @@ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo= -gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= -gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314= gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= -gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A= -gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/wagfarm-ui/Dockerfile b/wagfarm-ui/Dockerfile new file mode 100644 index 0000000..dc5c2ec --- /dev/null +++ b/wagfarm-ui/Dockerfile @@ -0,0 +1,8 @@ +# Use Nginx as the base image +FROM nginx:alpine + +# Copy the frontend files into the Nginx default directory +COPY ./ /usr/share/nginx/html + +# Expose the default Nginx port (80) +EXPOSE 80 diff --git a/wagfarm-ui/css/forms.css b/wagfarm-ui/css/forms.css new file mode 100644 index 0000000..35ab746 --- /dev/null +++ b/wagfarm-ui/css/forms.css @@ -0,0 +1,39 @@ +/* forms.css */ +.form-group { + margin-bottom: 1rem; + } + + label { + display: block; + margin-bottom: 0.5rem; + font-weight: bold; + } + + input[type="text"], + input[type="date"], + textarea, + select { + width: 100%; + padding: 0.5rem; + border: 1px solid #ddd; + border-radius: 3px; + font-size: 1rem; + } + + textarea { + height: 100px; + } + + button[type="submit"] { + background: #4a7c59; + color: white; + border: none; + padding: 0.7rem 1rem; + cursor: pointer; + font-size: 1rem; + border-radius: 3px; + } + + button[type="submit"]:hover { + background: #3d6549; + } \ No newline at end of file diff --git a/wagfarm-ui/css/style.css b/wagfarm-ui/css/style.css new file mode 100644 index 0000000..1c8051d --- /dev/null +++ b/wagfarm-ui/css/style.css @@ -0,0 +1,120 @@ +/* styles.css */ +* { + box-sizing: border-box; + margin: 0; + padding: 0; + } + + body { + font-family: Arial, sans-serif; + line-height: 1.6; + color: #333; + } + + header { + background: #4a7c59; + color: #fff; + padding: 1rem; + } + + header h1 { + margin-bottom: 1rem; + } + + nav ul { + display: flex; + list-style: none; + } + + nav ul li { + margin-right: 1rem; + } + + nav ul li a { + color: #fff; + text-decoration: none; + padding: 0.5rem; + } + + nav ul li a.active { + background: #fff; + color: #4a7c59; + border-radius: 3px; + } + + .container { + display: flex; + max-width: 1200px; + margin: 0 auto; + padding: 1rem; + } + + .sidebar { + flex: 1; + margin-right: 2rem; + } + + .content { + flex: 3; + } + + .log-item, .asset-item, .taxonomy-item { + border: 1px solid #ddd; + padding: 1rem; + margin-bottom: 1rem; + border-radius: 3px; + } + + .actions { + margin-top: 0.5rem; + } + + .actions button { + padding: 0.3rem 0.5rem; + margin-right: 0.5rem; + cursor: pointer; + } + + .view-btn { + background: #4a7c59; + color: white; + border: none; + } + + .edit-btn { + background: #f9a826; + color: white; + border: none; + } + + .delete-btn { + background: #e74c3c; + color: white; + border: none; + } + + .notification { + position: fixed; + top: 20px; + right: 20px; + padding: 10px 20px; + border-radius: 5px; + color: white; + z-index: 1000; + } + + .notification.success { + background-color: #2ecc71; + } + + .notification.error { + background-color: #e74c3c; + } + + footer { + background: #333; + color: #fff; + text-align: center; + padding: 1rem; + margin-top: 2rem; + } \ No newline at end of file diff --git a/wagfarm-ui/index.html b/wagfarm-ui/index.html new file mode 100644 index 0000000..ae300b5 --- /dev/null +++ b/wagfarm-ui/index.html @@ -0,0 +1,86 @@ + + + + + + Farm Work Tracker + + + + +
+

Farm Work Tracker

+ +
+ +
+
+ + +
+
+

Entity List

+
+
+ +
+

Details

+
+
+ + +
+
+
+ + + + + + \ No newline at end of file diff --git a/wagfarm-ui/js/api.js b/wagfarm-ui/js/api.js new file mode 100644 index 0000000..9a09c19 --- /dev/null +++ b/wagfarm-ui/js/api.js @@ -0,0 +1,64 @@ +// api.js +const API = { + baseUrl: 'https://your-api-url.com/api', + + async get(endpoint) { + try { + const response = await fetch(`${this.baseUrl}/${endpoint}`); + if (!response.ok) throw new Error(`API Error: ${response.status}`); + return await response.json(); + } catch (error) { + console.error('GET request failed:', error); + throw error; + } + }, + + async post(endpoint, data) { + try { + const response = await fetch(`${this.baseUrl}/${endpoint}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }); + if (!response.ok) throw new Error(`API Error: ${response.status}`); + return await response.json(); + } catch (error) { + console.error('POST request failed:', error); + throw error; + } + }, + + async put(endpoint, data) { + try { + const response = await fetch(`${this.baseUrl}/${endpoint}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }); + if (!response.ok) throw new Error(`API Error: ${response.status}`); + return await response.json(); + } catch (error) { + console.error('PUT request failed:', error); + throw error; + } + }, + + async delete(endpoint) { + try { + const response = await fetch(`${this.baseUrl}/${endpoint}`, { + method: 'DELETE' + }); + if (!response.ok) throw new Error(`API Error: ${response.status}`); + return await response.json(); + } catch (error) { + console.error('DELETE request failed:', error); + throw error; + } + } + }; + + export default API; \ No newline at end of file diff --git a/wagfarm-ui/js/app.js b/wagfarm-ui/js/app.js new file mode 100644 index 0000000..6b6e429 --- /dev/null +++ b/wagfarm-ui/js/app.js @@ -0,0 +1,109 @@ +import LogsModule from './entities/logs.js'; +import AssetsModule from './entities/assets.js'; +import TaxonomiesModule from './entities/taxonomies.js'; + +// State to track which entity type is active +let activeEntityType = 'logs'; + +document.addEventListener('DOMContentLoaded', () => { + // Initialize navigation + setupNavigation(); + + // Load the default entity type + loadEntityList(activeEntityType); + + // Setup form handlers + setupFormHandlers(); +}); + +function setupNavigation() { + const navLinks = document.querySelectorAll('.nav-link'); + + navLinks.forEach(link => { + link.addEventListener('click', (e) => { + e.preventDefault(); + const entityType = e.target.dataset.entity; + + // Update active link + navLinks.forEach(l => l.classList.remove('active')); + e.target.classList.add('active'); + + // Update active entity and load data + activeEntityType = entityType; + loadEntityList(entityType); + + // Show the appropriate form + document.querySelectorAll('.entity-form').forEach(form => { + form.style.display = 'none'; + }); + document.getElementById(`${entityType}-form-container`).style.display = 'block'; + }); + }); +} + +async function loadEntityList(entityType) { + // Clear previous content + document.getElementById('entity-list').innerHTML = '

Loading...

'; + + try { + let entities; + + // Get data based on entity type + switch(entityType) { + case 'logs': + entities = await LogsModule.getAllLogs(); + LogsModule.renderLogsList(entities, 'entity-list'); + break; + case 'assets': + entities = await AssetsModule.getAllAssets(); + AssetsModule.renderAssetsList(entities, 'entity-list'); + break; + case 'taxonomies': + entities = await TaxonomiesModule.getAllTaxonomies(); + TaxonomiesModule.renderTaxonomiesList(entities, 'entity-list'); + break; + } + } catch (error) { + document.getElementById('entity-list').innerHTML = `

Error loading data: ${error.message}

`; + } +} + +function setupFormHandlers() { + // Log creation form + document.getElementById('log-create-form').addEventListener('submit', async (e) => { + e.preventDefault(); + const formData = new FormData(e.target); + const logData = { + title: formData.get('title'), + date: formData.get('date'), + description: formData.get('description') + // Add more fields as needed + }; + + try { + await LogsModule.createLog(logData); + e.target.reset(); + if (activeEntityType === 'logs') { + loadEntityList('logs'); + } + showNotification('Log created successfully'); + } catch (error) { + showNotification(`Error: ${error.message}`, 'error'); + } + }); + + // Add similar handlers for assets and taxonomies +} + +function showNotification(message, type = 'success') { + const notification = document.createElement('div'); + notification.className = `notification ${type}`; + notification.textContent = message; + + document.body.appendChild(notification); + + // Remove after 3 seconds + setTimeout(() => { + notification.remove(); + }, 3000); +} \ No newline at end of file diff --git a/wagfarm-ui/js/entities/assets.js b/wagfarm-ui/js/entities/assets.js new file mode 100644 index 0000000..e69de29 diff --git a/wagfarm-ui/js/entities/logs.js b/wagfarm-ui/js/entities/logs.js new file mode 100644 index 0000000..2cc1773 --- /dev/null +++ b/wagfarm-ui/js/entities/logs.js @@ -0,0 +1,102 @@ +// logs.js +import API from '../api.js'; + +const LogsModule = { + async getAllLogs() { + return await API.get('logs'); + }, + + async getLog(id) { + return await API.get(`logs/${id}`); + }, + + async createLog(logData) { + return await API.post('logs', logData); + }, + + async updateLog(id, logData) { + return await API.put(`logs/${id}`, logData); + }, + + async deleteLog(id) { + return await API.delete(`logs/${id}`); + }, + + renderLogsList(logs, containerId) { + const container = document.getElementById(containerId); + container.innerHTML = ''; + + logs.forEach(log => { + const logElement = document.createElement('div'); + logElement.className = 'log-item'; + logElement.innerHTML = ` +

${log.title || 'Untitled Log'}

+

${log.date || 'No date'}

+
+ + + +
+ `; + container.appendChild(logElement); + }); + + // Add event listeners + this.addEventListeners(containerId); + }, + + addEventListeners(containerId) { + const container = document.getElementById(containerId); + + container.addEventListener('click', async (e) => { + const id = e.target.dataset.id; + if (!id) return; + + if (e.target.classList.contains('view-btn')) { + const log = await this.getLog(id); + // Display log details + document.getElementById('detail-view').innerHTML = ` +

${log.title || 'Untitled Log'}

+

Date: ${log.date || 'No date'}

+

Description: ${log.description || 'No description'}

+ + `; + } else if (e.target.classList.contains('edit-btn')) { + const log = await this.getLog(id); + // Populate edit form + document.getElementById('edit-form').innerHTML = ` +
+ + + + +
+ `; + + document.getElementById('log-edit-form').addEventListener('submit', async (e) => { + e.preventDefault(); + const formData = new FormData(e.target); + const logData = { + title: formData.get('title'), + date: formData.get('date'), + description: formData.get('description') + }; + + await this.updateLog(id, logData); + // Refresh the list + const logs = await this.getAllLogs(); + this.renderLogsList(logs, containerId); + }); + } else if (e.target.classList.contains('delete-btn')) { + if (confirm('Are you sure you want to delete this log?')) { + await this.deleteLog(id); + // Refresh the list + const logs = await this.getAllLogs(); + this.renderLogsList(logs, containerId); + } + } + }); + } +}; + +export default LogsModule; \ No newline at end of file diff --git a/wagfarm-ui/js/entities/taxonomy.js b/wagfarm-ui/js/entities/taxonomy.js new file mode 100644 index 0000000..e69de29 diff --git a/wagfarm-ui/js/util.js b/wagfarm-ui/js/util.js new file mode 100644 index 0000000..e69de29