Events-WebAPI fix and tweak
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -501,6 +501,7 @@ typings/
|
|||||||
#bower and libman wwwroot/lib
|
#bower and libman wwwroot/lib
|
||||||
**/wwwroot/lib
|
**/wwwroot/lib
|
||||||
**/logs/internal-nlog.txt
|
**/logs/internal-nlog.txt
|
||||||
|
Events-WebApi/Events.FilesAPI/GeneratedFiles/
|
||||||
|
|
||||||
# some needed exceptions
|
# some needed exceptions
|
||||||
/DataGenerator/.dotnet/.dotnet
|
/DataGenerator/.dotnet/.dotnet
|
||||||
|
|||||||
12
Events-WebApi/Events.ClientApp/package-lock.json
generated
12
Events-WebApi/Events.ClientApp/package-lock.json
generated
@@ -1488,9 +1488,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.8",
|
"version": "8.5.14",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz",
|
||||||
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
|
"integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -1630,9 +1630,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.4.1",
|
"version": "6.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz",
|
||||||
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
"integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -254,9 +254,13 @@ watch(eventsCatalogVersion, () => {
|
|||||||
filterDisplay="menu"
|
filterDisplay="menu"
|
||||||
lazy
|
lazy
|
||||||
paginator
|
paginator
|
||||||
|
paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
|
||||||
|
showCurrentPageReport
|
||||||
:rows="pageSize"
|
:rows="pageSize"
|
||||||
|
:rowsPerPageOptions="[10, 25, 50, 100]"
|
||||||
:first="(page - 1) * pageSize"
|
:first="(page - 1) * pageSize"
|
||||||
:total-records="totalRecords"
|
:total-records="totalRecords"
|
||||||
|
currentPageReportTemplate="{first} to {last} of {totalRecords}"
|
||||||
:sort-field="sort"
|
:sort-field="sort"
|
||||||
:sort-order="sortOrder"
|
:sort-order="sortOrder"
|
||||||
@filter="onFilter"
|
@filter="onFilter"
|
||||||
|
|||||||
@@ -327,9 +327,13 @@ onMounted(async () => {
|
|||||||
filterDisplay="menu"
|
filterDisplay="menu"
|
||||||
lazy
|
lazy
|
||||||
paginator
|
paginator
|
||||||
|
paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
|
||||||
|
showCurrentPageReport
|
||||||
:rows="pageSize"
|
:rows="pageSize"
|
||||||
|
:rowsPerPageOptions="[10, 25, 50, 100]"
|
||||||
:first="(page - 1) * pageSize"
|
:first="(page - 1) * pageSize"
|
||||||
:total-records="totalRecords"
|
:total-records="totalRecords"
|
||||||
|
currentPageReportTemplate="{first} to {last} of {totalRecords}"
|
||||||
:sort-field="sort"
|
:sort-field="sort"
|
||||||
:sort-order="sortOrder"
|
:sort-order="sortOrder"
|
||||||
@filter="onFilter"
|
@filter="onFilter"
|
||||||
|
|||||||
@@ -405,9 +405,13 @@ onMounted(async () => {
|
|||||||
filterDisplay="menu"
|
filterDisplay="menu"
|
||||||
lazy
|
lazy
|
||||||
paginator
|
paginator
|
||||||
|
paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
|
||||||
|
showCurrentPageReport
|
||||||
:rows="pageSize"
|
:rows="pageSize"
|
||||||
|
:rowsPerPageOptions="[10, 25, 50, 100]"
|
||||||
:first="(page - 1) * pageSize"
|
:first="(page - 1) * pageSize"
|
||||||
:total-records="totalRecords"
|
:total-records="totalRecords"
|
||||||
|
currentPageReportTemplate="{first} to {last} of {totalRecords}"
|
||||||
:sort-field="sort"
|
:sort-field="sort"
|
||||||
:sort-order="sortOrder"
|
:sort-order="sortOrder"
|
||||||
@filter="onFilter"
|
@filter="onFilter"
|
||||||
@@ -500,8 +504,8 @@ onMounted(async () => {
|
|||||||
optionLabel="name"
|
optionLabel="name"
|
||||||
:minLength="1"
|
:minLength="1"
|
||||||
completeOnFocus
|
completeOnFocus
|
||||||
dropdown
|
fluid
|
||||||
dropdownMode="current"
|
showClear
|
||||||
force-selection
|
force-selection
|
||||||
@complete="completePeopleLookup"
|
@complete="completePeopleLookup"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -188,9 +188,13 @@ onMounted(() => {
|
|||||||
filterDisplay="menu"
|
filterDisplay="menu"
|
||||||
lazy
|
lazy
|
||||||
paginator
|
paginator
|
||||||
|
paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
|
||||||
|
showCurrentPageReport
|
||||||
:rows="pageSize"
|
:rows="pageSize"
|
||||||
|
:rowsPerPageOptions="[10, 25, 50, 100]"
|
||||||
:first="(page - 1) * pageSize"
|
:first="(page - 1) * pageSize"
|
||||||
:total-records="totalRecords"
|
:total-records="totalRecords"
|
||||||
|
currentPageReportTemplate="{first} to {last} of {totalRecords}"
|
||||||
:sort-field="sort"
|
:sort-field="sort"
|
||||||
:sort-order="sortOrder"
|
:sort-order="sortOrder"
|
||||||
@filter="onFilter"
|
@filter="onFilter"
|
||||||
|
|||||||
@@ -42,6 +42,28 @@ body {
|
|||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 8px 24px rgba(15, 35, 56, 0.06);
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 8px 24px rgba(15, 35, 56, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel-card .p-paginator {
|
||||||
|
position: relative;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-card .p-paginator-current {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.panel-card .p-paginator {
|
||||||
|
justify-content: flex-start;
|
||||||
|
row-gap: 0.5rem;
|
||||||
|
padding-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-card .p-paginator-current {
|
||||||
|
top: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.tabs-header-bar {
|
.tabs-header-bar {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto 1fr;
|
grid-template-columns: 1fr auto 1fr;
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
using Events.Auth;
|
using Events.Auth;
|
||||||
|
using Events.FilesAPI.Features.Certificates.Download;
|
||||||
|
using Events.FilesAPI.Features.Certificates.Synchronize;
|
||||||
|
using Events.FilesAPI.Features.RegistrationsExcel.Download;
|
||||||
|
using Events.FilesAPI.Features.RegistrationsExcel.Synchronize;
|
||||||
using Events.FilesAPI.Infrastructure.Messaging;
|
using Events.FilesAPI.Infrastructure.Messaging;
|
||||||
using Events.FilesAPI.Infrastructure.Options;
|
using Events.FilesAPI.Infrastructure.Options;
|
||||||
using Events.WebAPI.Handlers.EF.Data.Postgres;
|
using Events.WebAPI.Handlers.EF.Data.Postgres;
|
||||||
@@ -19,6 +23,11 @@ builder.Services.AddOptions<GeneratedFilesOptions>()
|
|||||||
"GeneratedFilesOptions:OutputPath must be configured.")
|
"GeneratedFilesOptions:OutputPath must be configured.")
|
||||||
.ValidateOnStart();
|
.ValidateOnStart();
|
||||||
|
|
||||||
|
builder.Services.AddTransient<CertificateFileGenerator>();
|
||||||
|
builder.Services.AddTransient<CertificateFileLocator>();
|
||||||
|
builder.Services.AddTransient<RegistrationsExcelFileGenerator>();
|
||||||
|
builder.Services.AddTransient<RegistrationsExcelFileLocator>();
|
||||||
|
|
||||||
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));
|
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));
|
||||||
|
|
||||||
builder.Services.SetupMassTransit(builder.Configuration);
|
builder.Services.SetupMassTransit(builder.Configuration);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"Password": "guest"
|
"Password": "guest"
|
||||||
},
|
},
|
||||||
"Paths": {
|
"Paths": {
|
||||||
"OutputPath": "./Certificates"
|
"OutputPath": "./GeneratedFiles"
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"EventsPostgres": "Host=localhost;Port=5432;Database=events;Username=sport;Password=go and look in the secrets file;Persist Security Info=True;"
|
"EventsPostgres": "Host=localhost;Port=5432;Database=events;Username=sport;Password=go and look in the secrets file;Persist Security Info=True;"
|
||||||
|
|||||||
@@ -159,6 +159,35 @@ Once the APIs are running:
|
|||||||
- most `WebAPI` endpoints require a bearer token
|
- most `WebAPI` endpoints require a bearer token
|
||||||
- `FilesAPI` download endpoints are also protected and require the `events:read` scope
|
- `FilesAPI` download endpoints are also protected and require the `events:read` scope
|
||||||
|
|
||||||
|
## Running Everything Without VS Code
|
||||||
|
|
||||||
|
From the `Events-WebApi` directory, you can start all three processes together with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./start-all.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This starts:
|
||||||
|
|
||||||
|
- `Events.WebAPI` on `https://localhost:7295`
|
||||||
|
- `Events.FilesAPI` on `https://localhost:7296`
|
||||||
|
- `Events.ClientApp` on `http://localhost:5173`
|
||||||
|
|
||||||
|
The script keeps all processes attached to the terminal and stops them together when you press `Ctrl+C`.
|
||||||
|
|
||||||
|
If you want to stop the stack from another terminal, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./stop-all.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Before the first run, make sure the client dependencies are installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd Events.ClientApp
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
## Running The Client App
|
## Running The Client App
|
||||||
|
|
||||||
See [Events.ClientApp/README.md](/C:/GitRepos/FPMOZ-PI/predavanja/Events-WebApi/Events.ClientApp/README.md:1) for more details.
|
See [Events.ClientApp/README.md](/C:/GitRepos/FPMOZ-PI/predavanja/Events-WebApi/Events.ClientApp/README.md:1) for more details.
|
||||||
@@ -180,7 +209,7 @@ npm run dev
|
|||||||
According to the current `appsettings.json`, the default is:
|
According to the current `appsettings.json`, the default is:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
./Certificates
|
./GeneratedFiles
|
||||||
```
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|||||||
86
Events-WebApi/start-all.sh
Executable file
86
Events-WebApi/start-all.sh
Executable file
@@ -0,0 +1,86 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
WEBAPI_PROJECT="$ROOT_DIR/Events.WebAPI/Events.WebAPI.csproj"
|
||||||
|
FILESAPI_PROJECT="$ROOT_DIR/Events.FilesAPI/Events.FilesAPI.csproj"
|
||||||
|
CLIENTAPP_DIR="$ROOT_DIR/Events.ClientApp"
|
||||||
|
|
||||||
|
pids=()
|
||||||
|
|
||||||
|
start_process() {
|
||||||
|
if command -v setsid >/dev/null 2>&1; then
|
||||||
|
setsid "$@" &
|
||||||
|
else
|
||||||
|
"$@" &
|
||||||
|
fi
|
||||||
|
|
||||||
|
pids+=($!)
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_process() {
|
||||||
|
local signal="$1"
|
||||||
|
local pid="$2"
|
||||||
|
|
||||||
|
kill "-$signal" -- "-$pid" 2>/dev/null || kill "-$signal" "$pid" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
local exit_code=$?
|
||||||
|
trap - INT TERM EXIT
|
||||||
|
|
||||||
|
if ((${#pids[@]} > 0)); then
|
||||||
|
echo
|
||||||
|
echo "Stopping Events stack..."
|
||||||
|
|
||||||
|
for pid in "${pids[@]}"; do
|
||||||
|
stop_process INT "$pid"
|
||||||
|
done
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
for pid in "${pids[@]}"; do
|
||||||
|
stop_process TERM "$pid"
|
||||||
|
done
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
for pid in "${pids[@]}"; do
|
||||||
|
stop_process KILL "$pid"
|
||||||
|
done
|
||||||
|
|
||||||
|
wait "${pids[@]}" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "$exit_code"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup INT TERM EXIT
|
||||||
|
|
||||||
|
if [[ ! -d "$CLIENTAPP_DIR/node_modules" ]]; then
|
||||||
|
echo "Missing node_modules in Events.ClientApp."
|
||||||
|
echo "Run: cd \"$CLIENTAPP_DIR\" && npm install"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$ROOT_DIR/stop-all.sh" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
echo "Starting Events.WebAPI on https://localhost:7295"
|
||||||
|
start_process dotnet run --launch-profile https --project "$WEBAPI_PROJECT"
|
||||||
|
|
||||||
|
echo "Starting Events.FilesAPI on https://localhost:7296"
|
||||||
|
start_process dotnet run --launch-profile https --project "$FILESAPI_PROJECT"
|
||||||
|
|
||||||
|
echo "Starting Events.ClientApp on http://localhost:5173"
|
||||||
|
start_process env CLIENTAPP_DIR="$CLIENTAPP_DIR" bash -c 'cd "$CLIENTAPP_DIR" && npm run dev'
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Events stack is starting."
|
||||||
|
echo "WebAPI: https://localhost:7295"
|
||||||
|
echo "FilesAPI: https://localhost:7296"
|
||||||
|
echo "ClientApp: http://localhost:5173"
|
||||||
|
echo
|
||||||
|
echo "Press Ctrl+C to stop all processes."
|
||||||
|
|
||||||
|
wait
|
||||||
36
Events-WebApi/stop-all.sh
Executable file
36
Events-WebApi/stop-all.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
kill_port() {
|
||||||
|
local port="$1"
|
||||||
|
local pids
|
||||||
|
|
||||||
|
pids="$(lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null || true)"
|
||||||
|
if [[ -z "$pids" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill $pids 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
pids="$(lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null || true)"
|
||||||
|
if [[ -n "$pids" ]]; then
|
||||||
|
kill -9 $pids 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Stopping Events.WebAPI..."
|
||||||
|
kill_port 7295
|
||||||
|
pkill -f "/Events.WebAPI/bin/.*/Events.WebAPI" || true
|
||||||
|
|
||||||
|
echo "Stopping Events.FilesAPI..."
|
||||||
|
kill_port 7296
|
||||||
|
pkill -f "/Events.FilesAPI/bin/.*/Events.FilesAPI" || true
|
||||||
|
|
||||||
|
echo "Stopping Events.ClientApp..."
|
||||||
|
kill_port 5173
|
||||||
|
pkill -f "Events.ClientApp.*node_modules/.bin/vite" || true
|
||||||
|
pkill -f "vite" || true
|
||||||
|
|
||||||
|
echo "Events stack stopped."
|
||||||
Reference in New Issue
Block a user