fix(feedback): Ntfy in Docker, ASCII-Titel und Skipper-Badge
NTFY_* an den Backend-Container durchreichen; En-Dash im Ntfy-Header durch ASCII-Strich ersetzen (ByteString-Fehler). Skipper-Badge klar als Account-Anzeige kennzeichnen; start-dev.sh prüft npm vor dem Start. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+12
-3
@@ -672,9 +672,18 @@ html.scheme-dark .themed-select-option.is-selected {
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
background: var(--app-btn-secondary-bg);
|
background: rgba(148, 163, 184, 0.08);
|
||||||
border: 1px solid var(--app-btn-secondary-border);
|
border: 1px solid rgba(148, 163, 184, 0.18);
|
||||||
color: var(--app-btn-secondary-text);
|
color: var(--app-text-muted);
|
||||||
|
cursor: default;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skipper-badge__name {
|
||||||
|
max-width: 140px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-icon {
|
.btn-icon {
|
||||||
|
|||||||
@@ -206,9 +206,13 @@ export default function LogbookDashboard({ onSelectLogbook, onLogout }: LogbookD
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Skipper profile */}
|
{/* Skipper profile */}
|
||||||
<div className="skipper-badge">
|
<div
|
||||||
<User size={16} />
|
className="skipper-badge"
|
||||||
<span>{username}</span>
|
title={t('dashboard.logged_in_as', { name: username })}
|
||||||
|
aria-label={t('dashboard.logged_in_as', { name: username })}
|
||||||
|
>
|
||||||
|
<User size={16} aria-hidden="true" />
|
||||||
|
<span className="skipper-badge__name">{username}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Lang toggle */}
|
{/* Lang toggle */}
|
||||||
|
|||||||
@@ -243,6 +243,7 @@
|
|||||||
"create_btn": "Logbuch erstellen",
|
"create_btn": "Logbuch erstellen",
|
||||||
"new_logbook_placeholder": "Name des Logbuchs oder der Yacht",
|
"new_logbook_placeholder": "Name des Logbuchs oder der Yacht",
|
||||||
"logout": "Abmelden",
|
"logout": "Abmelden",
|
||||||
|
"logged_in_as": "Angemeldet als {{name}}",
|
||||||
"delete_confirm": "Sind Sie sicher, dass Sie dieses Logbuch unwiderruflich löschen möchten? Alle lokalen Daten und Server-Kopien werden vernichtet.\n\nTipp: Erstellen Sie vorher unter Einstellungen → Backup & Wiederherstellung eine Sicherungskopie (.daagbok.json), falls Sie die Daten später behalten möchten.",
|
"delete_confirm": "Sind Sie sicher, dass Sie dieses Logbuch unwiderruflich löschen möchten? Alle lokalen Daten und Server-Kopien werden vernichtet.\n\nTipp: Erstellen Sie vorher unter Einstellungen → Backup & Wiederherstellung eine Sicherungskopie (.daagbok.json), falls Sie die Daten später behalten möchten.",
|
||||||
"no_logbooks": "Keine Logbücher gefunden. Erstellen Sie Ihr erstes Logbuch, um zu beginnen!",
|
"no_logbooks": "Keine Logbücher gefunden. Erstellen Sie Ihr erstes Logbuch, um zu beginnen!",
|
||||||
"loading": "Logbücher werden geladen...",
|
"loading": "Logbücher werden geladen...",
|
||||||
|
|||||||
@@ -243,6 +243,7 @@
|
|||||||
"create_btn": "Create Logbook",
|
"create_btn": "Create Logbook",
|
||||||
"new_logbook_placeholder": "Logbook or Yacht Name",
|
"new_logbook_placeholder": "Logbook or Yacht Name",
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
|
"logged_in_as": "Signed in as {{name}}",
|
||||||
"delete_confirm": "Are you sure you want to permanently delete this logbook? All local data and server copies will be destroyed.\n\nTip: Create a backup first under Settings → Backup & restore (.daagbok.json) if you may need the data later.",
|
"delete_confirm": "Are you sure you want to permanently delete this logbook? All local data and server copies will be destroyed.\n\nTip: Create a backup first under Settings → Backup & restore (.daagbok.json) if you may need the data later.",
|
||||||
"no_logbooks": "No logbooks found. Create your first logbook to begin!",
|
"no_logbooks": "No logbooks found. Create your first logbook to begin!",
|
||||||
"loading": "Loading logbooks...",
|
"loading": "Loading logbooks...",
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ services:
|
|||||||
VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY:-}
|
VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY:-}
|
||||||
VAPID_SUBJECT: ${VAPID_SUBJECT:-mailto:support@kapteins-daagbok.eu}
|
VAPID_SUBJECT: ${VAPID_SUBJECT:-mailto:support@kapteins-daagbok.eu}
|
||||||
OpenWeatherMapAPIKey: ${OpenWeatherMapAPIKey:-}
|
OpenWeatherMapAPIKey: ${OpenWeatherMapAPIKey:-}
|
||||||
|
NTFY_SERVER: ${NTFY_SERVER:-https://ntfy.sh}
|
||||||
|
NTFY_TOPIC: ${NTFY_TOPIC:-}
|
||||||
|
NTFY_TOKEN: ${NTFY_TOKEN:-}
|
||||||
command: sh -c "npx prisma db push && node dist/index.js"
|
command: sh -c "npx prisma db push && node dist/index.js"
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
|
|||||||
+80
-4
@@ -3,12 +3,66 @@
|
|||||||
# Configuration
|
# Configuration
|
||||||
SERVER_PORT=5000
|
SERVER_PORT=5000
|
||||||
CLIENT_PORT=5173
|
CLIENT_PORT=5173
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
|
||||||
|
resolve_node_toolchain() {
|
||||||
|
# Common install locations when login shell PATH is not loaded
|
||||||
|
if command -v npm >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -s "$HOME/.nvm/nvm.sh" ]; then
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "$HOME/.nvm/nvm.sh"
|
||||||
|
elif [ -s "/usr/local/nvm/nvm.sh" ]; then
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "/usr/local/nvm/nvm.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$HOME/.fnm" ] && command -v fnm >/dev/null 2>&1; then
|
||||||
|
eval "$(fnm env)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for candidate in \
|
||||||
|
/usr/local/bin/npm \
|
||||||
|
/usr/bin/npm \
|
||||||
|
"$HOME/.local/share/fnm/current/bin/npm" \
|
||||||
|
"$HOME/.nvm/versions/node/"*/bin/npm; do
|
||||||
|
if [ -x "$candidate" ]; then
|
||||||
|
export PATH="$(dirname "$candidate"):$PATH"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
command -v npm >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
require_node_toolchain() {
|
||||||
|
if resolve_node_toolchain; then
|
||||||
|
echo "Using Node $(node -v), npm $(npm -v)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Error: npm was not found in PATH."
|
||||||
|
echo ""
|
||||||
|
echo "This script starts local Vite/Express dev servers and requires Node.js 20+ with npm."
|
||||||
|
echo "Install Node.js on this machine, or use the Docker-based stack instead:"
|
||||||
|
echo " ./scripts/start-dev-docker.sh"
|
||||||
|
echo ""
|
||||||
|
echo "On the production host, prefer updating the running stack:"
|
||||||
|
echo " docker compose -f docker-compose.yml up -d --build"
|
||||||
|
echo " # or from your workstation: ./scripts/update-prod.sh"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
echo " Kapteins Daagbok Dev Environment "
|
echo " Kapteins Daagbok Dev Environment "
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
echo "Preparing to (re)start services..."
|
echo "Preparing to (re)start services..."
|
||||||
|
|
||||||
|
require_node_toolchain
|
||||||
|
|
||||||
# Clean up processes running on ports
|
# Clean up processes running on ports
|
||||||
cleanup_port() {
|
cleanup_port() {
|
||||||
local port=$1
|
local port=$1
|
||||||
@@ -77,18 +131,40 @@ fi
|
|||||||
|
|
||||||
# Start backend server
|
# Start backend server
|
||||||
echo "Starting backend API server..."
|
echo "Starting backend API server..."
|
||||||
cd server
|
cd "$REPO_ROOT/server" || exit 1
|
||||||
|
if [ ! -d node_modules ]; then
|
||||||
|
echo "Error: server/node_modules missing. Run: cd server && npm ci"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
npm run dev &
|
npm run dev &
|
||||||
cd ..
|
BACKEND_PID=$!
|
||||||
|
cd "$REPO_ROOT" || exit 1
|
||||||
|
|
||||||
# Sleep briefly to let server start up
|
# Sleep briefly to let server start up
|
||||||
sleep 1.5
|
sleep 1.5
|
||||||
|
if ! kill -0 "$BACKEND_PID" 2>/dev/null; then
|
||||||
|
echo "Error: Backend dev server exited immediately. Check server logs above."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Start frontend client
|
# Start frontend client
|
||||||
echo "Starting frontend dev server..."
|
echo "Starting frontend dev server..."
|
||||||
cd client
|
cd "$REPO_ROOT/client" || exit 1
|
||||||
|
if [ ! -d node_modules ]; then
|
||||||
|
echo "Error: client/node_modules missing. Run: cd client && npm ci"
|
||||||
|
kill "$BACKEND_PID" 2>/dev/null
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
npm run dev &
|
npm run dev &
|
||||||
cd ..
|
CLIENT_PID=$!
|
||||||
|
cd "$REPO_ROOT" || exit 1
|
||||||
|
|
||||||
|
sleep 1.5
|
||||||
|
if ! kill -0 "$CLIENT_PID" 2>/dev/null; then
|
||||||
|
echo "Error: Frontend dev server exited immediately. Check client logs above."
|
||||||
|
kill "$BACKEND_PID" 2>/dev/null
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
echo "Dev services are now running:"
|
echo "Dev services are now running:"
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export async function sendFeedbackViaNtfy(payload: FeedbackPayload): Promise<voi
|
|||||||
}
|
}
|
||||||
|
|
||||||
const categoryLabel = payload.category.charAt(0).toUpperCase() + payload.category.slice(1)
|
const categoryLabel = payload.category.charAt(0).toUpperCase() + payload.category.slice(1)
|
||||||
const title = `Kapteins Daagbok – ${categoryLabel}`
|
const title = `Kapteins Daagbok - ${categoryLabel}`
|
||||||
|
|
||||||
const lines = [
|
const lines = [
|
||||||
payload.message,
|
payload.message,
|
||||||
|
|||||||
Reference in New Issue
Block a user