Compare commits

...

2 Commits

Author SHA1 Message Date
opencode d47db6d386 docs: add v0.8.5 release notes
Build & Push Docker Image / build (push) Successful in 3m43s
2026-08-04 21:01:58 +02:00
opencode 70e72dac71 fix(i18n): translate submit button, density/view toggles; rename watchlist guide to Merkliste; add guide help buttons
Build & Push Docker Image / build (push) Successful in 2m31s
2026-08-04 20:43:36 +02:00
25 changed files with 197 additions and 47 deletions
@@ -15,6 +15,7 @@ import {
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { useAuth } from "@/hooks/use-auth"; import { useAuth } from "@/hooks/use-auth";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { GuideHelp } from "@/components/guide-help";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
@@ -105,7 +106,10 @@ export function AdminToolsTab() {
<Card> <Card>
<CardHeader className="flex flex-row items-center justify-between gap-4 flex-wrap"> <CardHeader className="flex flex-row items-center justify-between gap-4 flex-wrap">
<div className="space-y-1.5"> <div className="space-y-1.5">
<CardTitle>{t("adminTools.allTools")}</CardTitle> <CardTitle className="flex items-center gap-2">
{t("adminTools.allTools")}
<GuideHelp guide="administration" label={t("adminTools.allTools")} />
</CardTitle>
<CardDescription> <CardDescription>
{selectedIds.length > 0 ? t("adminTools.selected", { count: selectedIds.length }) : t("adminTools.toolCount", { count: allTools.length })} {selectedIds.length > 0 ? t("adminTools.selected", { count: selectedIds.length }) : t("adminTools.toolCount", { count: allTools.length })}
</CardDescription> </CardDescription>
@@ -1,5 +1,6 @@
import { Slider } from "@/components/ui/slider"; import { Slider } from "@/components/ui/slider";
import { Maximize2, Minimize2 } from "lucide-react"; import { Maximize2, Minimize2 } from "lucide-react";
import { useTranslation } from "react-i18next";
export type Density = "cozy" | "compact"; export type Density = "cozy" | "compact";
@@ -10,8 +11,13 @@ export function DensityToggle({
value: Density; value: Density;
onValueChange: (d: Density) => void; onValueChange: (d: Density) => void;
}) { }) {
const { t } = useTranslation();
const densityLabel = value === "compact" ? t("common.densityCompact") : t("common.densityComfortable");
return ( return (
<div className="flex items-center gap-2" title={`Density: ${value === "compact" ? "Compact" : "Comfortable"}`}> <div
className="flex items-center gap-2"
title={t("common.densityTitle", { density: densityLabel })}
>
<Maximize2 className="w-4 h-4 text-muted-foreground" aria-hidden /> <Maximize2 className="w-4 h-4 text-muted-foreground" aria-hidden />
<Slider <Slider
className="w-16" className="w-16"
@@ -20,7 +26,7 @@ export function DensityToggle({
step={1} step={1}
value={[value === "compact" ? 1 : 0]} value={[value === "compact" ? 1 : 0]}
onValueChange={([v]) => onValueChange(v === 1 ? "compact" : "cozy")} onValueChange={([v]) => onValueChange(v === 1 ? "compact" : "cozy")}
aria-label="List density" aria-label={t("common.listDensity")}
/> />
<Minimize2 className="w-4 h-4 text-muted-foreground" aria-hidden /> <Minimize2 className="w-4 h-4 text-muted-foreground" aria-hidden />
</div> </div>
@@ -105,7 +105,7 @@ export function FilterPopover({
step={0.5} step={0.5}
value={[minRating ?? 0]} value={[minRating ?? 0]}
onValueChange={([v]) => onChange({ minRating: v })} onValueChange={([v]) => onChange({ minRating: v })}
aria-label="Minimum rating" aria-label={t("filter.minRating")}
/> />
<span className="text-sm tabular-nums w-8 text-right text-muted-foreground"> <span className="text-sm tabular-nums w-8 text-right text-muted-foreground">
{minRating != null ? `${minRating.toFixed(1)}+` : t("filter.any")} {minRating != null ? `${minRating.toFixed(1)}+` : t("filter.any")}
@@ -17,6 +17,7 @@ import {
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { PasswordInput } from "@/components/password-input"; import { PasswordInput } from "@/components/password-input";
import { GuideHelp } from "@/components/guide-help";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
import { useChangeMyPassword, useGetPasswordRedirect, getGetPasswordRedirectQueryKey } from "@workspace/api-client-react"; import { useChangeMyPassword, useGetPasswordRedirect, getGetPasswordRedirectQueryKey } from "@workspace/api-client-react";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
@@ -164,7 +165,10 @@ export function UserMenu() {
<Dialog open={pwOpen} onOpenChange={setPwOpen}> <Dialog open={pwOpen} onOpenChange={setPwOpen}>
<DialogContent className="sm:max-w-md"> <DialogContent className="sm:max-w-md">
<DialogHeader> <DialogHeader>
<DialogTitle>{t("auth.changePassword")}</DialogTitle> <DialogTitle className="flex items-center gap-2">
{t("auth.changePassword")}
<GuideHelp guide="konto" label={t("auth.changePassword")} />
</DialogTitle>
</DialogHeader> </DialogHeader>
{!user?.isLocal ? ( {!user?.isLocal ? (
<div className="space-y-4 py-2"> <div className="space-y-4 py-2">
@@ -193,7 +197,7 @@ export function UserMenu() {
<PasswordInput <PasswordInput
value={newPassword} value={newPassword}
onChange={(e) => setNewPassword(e.target.value)} onChange={(e) => setNewPassword(e.target.value)}
placeholder="min. 6 characters" placeholder={t("auth.passwordMinLength")}
data-testid="input-new-password" data-testid="input-new-password"
/> />
</div> </div>
@@ -1,12 +1,13 @@
import { LayoutGrid, List, Rows3 } from "lucide-react"; import { LayoutGrid, List, Rows3 } from "lucide-react";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { useTranslation } from "react-i18next";
export type ViewMode = "grid" | "table" | "rows"; export type ViewMode = "grid" | "table" | "rows";
const OPTIONS: { value: ViewMode; label: string; Icon: typeof LayoutGrid }[] = [ const OPTIONS: { value: ViewMode; labelKey: string; Icon: typeof LayoutGrid }[] = [
{ value: "grid", label: "Grid", Icon: LayoutGrid }, { value: "grid", labelKey: "common.viewGrid", Icon: LayoutGrid },
{ value: "table", label: "Table", Icon: List }, { value: "table", labelKey: "common.viewTable", Icon: List },
{ value: "rows", label: "Rows", Icon: Rows3 }, { value: "rows", labelKey: "common.viewRows", Icon: Rows3 },
]; ];
export function ViewToggle({ export function ViewToggle({
@@ -16,6 +17,7 @@ export function ViewToggle({
value: ViewMode; value: ViewMode;
onValueChange: (v: ViewMode) => void; onValueChange: (v: ViewMode) => void;
}) { }) {
const { t } = useTranslation();
return ( return (
<ToggleGroup <ToggleGroup
type="single" type="single"
@@ -25,10 +27,16 @@ export function ViewToggle({
}} }}
variant="outline" variant="outline"
size="sm" size="sm"
aria-label="View mode" aria-label={t("common.viewMode")}
> >
{OPTIONS.map(({ value: v, label, Icon }) => ( {OPTIONS.map(({ value: v, labelKey, Icon }) => (
<ToggleGroupItem key={v} value={v} aria-label={label} title={label} data-testid={`view-${v}`}> <ToggleGroupItem
key={v}
value={v}
aria-label={t(labelKey)}
title={t(labelKey)}
data-testid={`view-${v}`}
>
<Icon className="w-4 h-4" /> <Icon className="w-4 h-4" />
</ToggleGroupItem> </ToggleGroupItem>
))} ))}
+11 -2
View File
@@ -30,6 +30,7 @@
"currentPassword": "Aktuelles Passwort", "currentPassword": "Aktuelles Passwort",
"newPassword": "Neues Passwort", "newPassword": "Neues Passwort",
"confirmPassword": "Passwort bestätigen", "confirmPassword": "Passwort bestätigen",
"passwordMinLength": "mind. 6 Zeichen",
"pwMismatch": "Passwörter stimmen nicht überein", "pwMismatch": "Passwörter stimmen nicht überein",
"pwTooShort": "Passwort muss mindestens 8 Zeichen haben", "pwTooShort": "Passwort muss mindestens 8 Zeichen haben",
"pwChanged": "Passwort geändert", "pwChanged": "Passwort geändert",
@@ -54,8 +55,16 @@
"all": "Alle", "all": "Alle",
"none": "Keine", "none": "Keine",
"language": "Sprache", "language": "Sprache",
"viewDetails": "Details ansehen", "viewDetails": "Details ansehen",
"guideTooltip": "Anleitung in der Dokumentation" "guideTooltip": "Anleitung in der Dokumentation",
"viewMode": "Ansichtsmodus",
"viewGrid": "Raster",
"viewTable": "Tabelle",
"viewRows": "Zeilen",
"listDensity": "Listendichte",
"densityCompact": "Kompakt",
"densityComfortable": "Komfortabel",
"densityTitle": "Dichte: {{density}}"
}, },
"home": { "home": {
"welcome": "Willkommen bei toolr", "welcome": "Willkommen bei toolr",
+11 -2
View File
@@ -30,6 +30,7 @@
"currentPassword": "Current password", "currentPassword": "Current password",
"newPassword": "New password", "newPassword": "New password",
"confirmPassword": "Confirm password", "confirmPassword": "Confirm password",
"passwordMinLength": "min. 6 characters",
"pwMismatch": "Passwords do not match", "pwMismatch": "Passwords do not match",
"pwTooShort": "Password must be at least 8 characters", "pwTooShort": "Password must be at least 8 characters",
"pwChanged": "Password changed", "pwChanged": "Password changed",
@@ -54,8 +55,16 @@
"all": "All", "all": "All",
"none": "None", "none": "None",
"language": "Language", "language": "Language",
"viewDetails": "View details", "viewDetails": "View details",
"guideTooltip": "Guide in the documentation" "guideTooltip": "Guide in the documentation",
"viewMode": "View mode",
"viewGrid": "Grid",
"viewTable": "Table",
"viewRows": "Rows",
"listDensity": "List density",
"densityCompact": "Compact",
"densityComfortable": "Comfortable",
"densityTitle": "Density: {{density}}"
}, },
"home": { "home": {
"welcome": "Welcome to toolr", "welcome": "Welcome to toolr",
+5 -1
View File
@@ -7,6 +7,7 @@ import {
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card"; import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { Layout } from "@/components/layout"; import { Layout } from "@/components/layout";
import { GuideHelp } from "@/components/guide-help";
import { ToolCard } from "@/components/tool-card"; import { ToolCard } from "@/components/tool-card";
import { Star, Wrench, MessageSquare, ArrowRight, Plus } from "lucide-react"; import { Star, Wrench, MessageSquare, ArrowRight, Plus } from "lucide-react";
import { Link } from "wouter"; import { Link } from "wouter";
@@ -24,7 +25,10 @@ export default function Home() {
<div className="space-y-8 pb-8"> <div className="space-y-8 pb-8">
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-end gap-4"> <div className="flex flex-col sm:flex-row justify-between items-start sm:items-end gap-4">
<div> <div>
<h1 className="text-3xl font-bold tracking-tight mb-2">{t("home.welcome")}</h1> <h1 className="text-3xl font-bold tracking-tight mb-2 flex items-center gap-2">
{t("home.welcome")}
<GuideHelp guide="getting-started" label={t("home.welcome")} />
</h1>
<p className="text-muted-foreground">{t("home.tagline")}</p> <p className="text-muted-foreground">{t("home.tagline")}</p>
</div> </div>
<Button asChild> <Button asChild>
+5 -1
View File
@@ -1,6 +1,7 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Layout } from "@/components/layout"; import { Layout } from "@/components/layout";
import { GuideHelp } from "@/components/guide-help";
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -46,7 +47,10 @@ export default function RedundancyPage() {
<div className="space-y-6"> <div className="space-y-6">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<AlertTriangle className="w-6 h-6 text-amber-500" /> <AlertTriangle className="w-6 h-6 text-amber-500" />
<h1 className="text-3xl font-bold">{t("redundancy.title")}</h1> <h1 className="text-3xl font-bold flex items-center gap-2">
{t("redundancy.title")}
<GuideHelp guide="redundanz" label={t("redundancy.title")} />
</h1>
</div> </div>
<p className="text-muted-foreground"> <p className="text-muted-foreground">
{t("redundancy.subtitle")} {t("redundancy.subtitle")}
+1 -1
View File
@@ -369,7 +369,7 @@ export default function ToolNew() {
className="w-full sm:w-auto" className="w-full sm:w-auto"
data-testid="button-submit-tool" data-testid="button-submit-tool"
> >
{createTool.isPending ? "Adding Tool..." : "Submit Tool"} {createTool.isPending ? t("toolForm.addingTool") : t("toolForm.submitTool")}
</Button> </Button>
</div> </div>
</form> </form>
@@ -6,6 +6,7 @@ import {
} from "@workspace/api-client-react"; } from "@workspace/api-client-react";
import { useVirtualizer } from "@tanstack/react-virtual"; import { useVirtualizer } from "@tanstack/react-virtual";
import { Layout } from "@/components/layout"; import { Layout } from "@/components/layout";
import { GuideHelp } from "@/components/guide-help";
import { ToolCard } from "@/components/tool-card"; import { ToolCard } from "@/components/tool-card";
import { ToolCardWide } from "@/components/tool-card-wide"; import { ToolCardWide } from "@/components/tool-card-wide";
import { ToolRow, TABLE_GRID } from "@/components/tool-row"; import { ToolRow, TABLE_GRID } from "@/components/tool-row";
@@ -230,7 +231,10 @@ export default function ToolsBrowse() {
<div className="space-y-6 pb-8"> <div className="space-y-6 pb-8">
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-end gap-4"> <div className="flex flex-col sm:flex-row justify-between items-start sm:items-end gap-4">
<div> <div>
<h1 className="text-3xl font-bold tracking-tight mb-2">{t("nav.browseTools")}</h1> <h1 className="text-3xl font-bold tracking-tight mb-2 flex items-center gap-2">
{t("nav.browseTools")}
<GuideHelp guide="tools-finden" label={t("browse.subtitle")} />
</h1>
<p className="text-muted-foreground">{t("browse.subtitle")}</p> <p className="text-muted-foreground">{t("browse.subtitle")}</p>
</div> </div>
<Button asChild> <Button asChild>
@@ -521,7 +525,10 @@ export default function ToolsBrowse() {
<AlertDialog open={compareUpsellOpen} onOpenChange={setCompareUpsellOpen}> <AlertDialog open={compareUpsellOpen} onOpenChange={setCompareUpsellOpen}>
<AlertDialogContent> <AlertDialogContent>
<AlertDialogHeader> <AlertDialogHeader>
<AlertDialogTitle>{t("browse.comparePremiumTitle")}</AlertDialogTitle> <AlertDialogTitle className="flex items-center gap-2">
{t("browse.comparePremiumTitle")}
<GuideHelp guide="plaene" label={t("browse.comparePremiumTitle")} />
</AlertDialogTitle>
<AlertDialogDescription> <AlertDialogDescription>
{t("browse.comparePremiumSub")} {t("browse.comparePremiumSub")}
</AlertDialogDescription> </AlertDialogDescription>
+5 -1
View File
@@ -15,6 +15,7 @@ import {
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { useAuth } from "@/hooks/use-auth"; import { useAuth } from "@/hooks/use-auth";
import { Layout } from "@/components/layout"; import { Layout } from "@/components/layout";
import { GuideHelp } from "@/components/guide-help";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
@@ -156,7 +157,10 @@ export default function Trash() {
<Layout> <Layout>
<div className="space-y-6 pb-10"> <div className="space-y-6 pb-10">
<div> <div>
<h1 className="text-3xl font-bold tracking-tight mb-2">{t("trash.title")}</h1> <h1 className="text-3xl font-bold tracking-tight mb-2 flex items-center gap-2">
{t("trash.title")}
<GuideHelp guide="papierkorb" label={t("trash.title")} />
</h1>
<p className="text-muted-foreground">{t("trash.subtitle")}</p> <p className="text-muted-foreground">{t("trash.subtitle")}</p>
</div> </div>
+2 -2
View File
@@ -10,7 +10,7 @@ Besuch bis zum Anlegen und Bewerten eines Tools.
## 1. Anmelden ## 1. Anmelden
Die meisten Aktionen (Tool anlegen, bewerten, Watchlist, Vergleichen) erfordern Die meisten Aktionen (Tool anlegen, bewerten, Merkliste, Vergleichen) erfordern
ein Konto. Klicke unten links auf **Anmelden**. Je nach Konfiguration der ein Konto. Klicke unten links auf **Anmelden**. Je nach Konfiguration der
Instanz hast du zwei Möglichkeiten: Instanz hast du zwei Möglichkeiten:
@@ -51,7 +51,7 @@ Siehe [Bewerten](/docs/handbook/bewerten).
## 5. Weiterführend ## 5. Weiterführend
- [Tools vergleichen](/docs/handbook/vergleichen) - [Tools vergleichen](/docs/handbook/vergleichen)
- [Watchlist](/docs/handbook/watchlist) - [Merkliste](/docs/handbook/watchlist)
- [Analytics](/docs/handbook/analytics) - [Analytics](/docs/handbook/analytics)
- [Pläne & Berechtigungen](/docs/handbook/plaene) - [Pläne & Berechtigungen](/docs/handbook/plaene)
- [Administration](/docs/handbook/administration) - [Administration](/docs/handbook/administration)
+1 -1
View File
@@ -18,7 +18,7 @@ die richtige Wahl zu treffen.
| **Tool anlegen** | Neues Tool mit Beschreibung, Kategorie, Features & Tags eintragen | Angemeldet | | **Tool anlegen** | Neues Tool mit Beschreibung, Kategorie, Features & Tags eintragen | Angemeldet |
| **Tool bearbeiten/löschen** | Eigene Tools pflegen (Ersteller:in oder Admin) | Angemeldet | | **Tool bearbeiten/löschen** | Eigene Tools pflegen (Ersteller:in oder Admin) | Angemeldet |
| **Bewerten** | Nützlichkeit & Bedienbarkeit (15) plus Kommentar vergeben | Angemeldet | | **Bewerten** | Nützlichkeit & Bedienbarkeit (15) plus Kommentar vergeben | Angemeldet |
| **Watchlist** | Tools als Favoriten speichern | Premium | | **Merkliste** | Tools als Favoriten speichern | Premium |
| **Vergleichen** | Tools nebeneinander gegenüberstellen | Premium | | **Vergleichen** | Tools nebeneinander gegenüberstellen | Premium |
| **Kosten erfassen** | Lizenz- und Kostenmodelle je Tool eintragen | Premium | | **Kosten erfassen** | Lizenz- und Kostenmodelle je Tool eintragen | Premium |
| **Analytics** | Statistiken, Top-Tools, Verteilungen | Alle | | **Analytics** | Statistiken, Top-Tools, Verteilungen | Alle |
+2 -2
View File
@@ -26,7 +26,7 @@ Der aktive Modus steht im Endpunkt
Dein Profil (Avatar, Name, E-Mail, Tarif) siehst du unten links im Dein Profil (Avatar, Name, E-Mail, Tarif) siehst du unten links im
Benutzermenü. Dort stehen dir folgende Aktionen zur Verfügung: Benutzermenü. Dort stehen dir folgende Aktionen zur Verfügung:
- **Watchlist** — deine gespeicherten Tools (nur mit dem entsprechenden Tarif). - **Merkliste** — deine gespeicherten Tools (nur mit dem entsprechenden Tarif).
- **Papierkorb** — wiederherstellbare, gelöschte Tools (Premium/Enterprise). - **Papierkorb** — wiederherstellbare, gelöschte Tools (Premium/Enterprise).
- **Passwort ändern** — für lokale Konten direkt in toolr; für OIDC-Konten wird - **Passwort ändern** — für lokale Konten direkt in toolr; für OIDC-Konten wird
die Passwortverwaltung im Identitätsanbieter angeboten. die Passwortverwaltung im Identitätsanbieter angeboten.
@@ -51,7 +51,7 @@ API-Referenz: [`POST /auth/me/password`](/docs/reference/endpoints/auth#changeMy
- die **Listenansicht** und **Dichte** im Bereich Tools durchsuchen anpassen - die **Listenansicht** und **Dichte** im Bereich Tools durchsuchen anpassen
(siehe [Tools finden & durchsuchen](/docs/handbook/tools-finden)). (siehe [Tools finden & durchsuchen](/docs/handbook/tools-finden)).
Deine Präferenzen (inkl. Watchlist) werden im Endpunkt Deine Präferenzen (inkl. Merkliste) werden im Endpunkt
[`GET /auth/me/preferences`](/docs/reference/endpoints/auth#getMePreferences) [`GET /auth/me/preferences`](/docs/reference/endpoints/auth#getMePreferences)
gespeichert und über [`PUT /auth/me/preferences`](/docs/reference/endpoints/auth#updateMePreferences) gespeichert und über [`PUT /auth/me/preferences`](/docs/reference/endpoints/auth#updateMePreferences)
aktualisiert. aktualisiert.
+2 -2
View File
@@ -13,7 +13,7 @@ Feature-Beschränkungen.
| Tarif | Beschreibung | | Tarif | Beschreibung |
| --- | --- | | --- | --- |
| **Free** | Grundfunktionen: suchen, filtern, ansehen, Analytics | | **Free** | Grundfunktionen: suchen, filtern, ansehen, Analytics |
| **Premium** | Zusätzlich Watchlist, Vergleichen, Papierkorb, Kosten | | **Premium** | Zusätzlich Merkliste, Vergleichen, Papierkorb, Kosten |
| **Enterprise** | Alle Premium-Features + erweiterter Support | | **Enterprise** | Alle Premium-Features + erweiterter Support |
### Feature-Berechtigungen ### Feature-Berechtigungen
@@ -23,7 +23,7 @@ Premium/Enterprise schalten folgende Features frei:
| Feature | Funktion | Mehr erfahren | | Feature | Funktion | Mehr erfahren |
| --- | --- | --- | | --- | --- | --- |
| `compare` | Tools vergleichen | [Vergleichen](/docs/handbook/vergleichen) | | `compare` | Tools vergleichen | [Vergleichen](/docs/handbook/vergleichen) |
| `watchlist` | Favoritenliste | [Watchlist](/docs/handbook/watchlist) | | `watchlist` | Favoritenliste | [Merkliste](/docs/handbook/watchlist) |
| `trash` | Papierkorb (soft gelöschte Tools) | [Papierkorb](/docs/handbook/papierkorb) | | `trash` | Papierkorb (soft gelöschte Tools) | [Papierkorb](/docs/handbook/papierkorb) |
| `costs` | Kosten-/Lizenzmodelle erfassen | [Kosten erfassen](/docs/handbook/kosten) | | `costs` | Kosten-/Lizenzmodelle erfassen | [Kosten erfassen](/docs/handbook/kosten) |
+1 -1
View File
@@ -19,7 +19,7 @@ Ohne Eingabe zeigt die Palette:
- **Zuletzt angesehen** — die letzten 5 Tools, die du besucht hast. - **Zuletzt angesehen** — die letzten 5 Tools, die du besucht hast.
- **Navigation** — Tools durchsuchen, Tool hinzufügen, Analytics sowie - **Navigation** — Tools durchsuchen, Tool hinzufügen, Analytics sowie
(abhängig von Berechtigungen) Watchlist, Papierkorb und Admin. (abhängig von Berechtigungen) Merkliste, Papierkorb und Admin.
### Suche ### Suche
+2 -2
View File
@@ -58,12 +58,12 @@ In der Tabellenansicht sind die Spalten **Tool**, **Bewertung** und **Anzahl
Bewertungen** sortierbar. Beim Überfahren einer Zeile erscheint eine Vorschau Bewertungen** sortierbar. Beim Überfahren einer Zeile erscheint eine Vorschau
mit Bewertungsdetails, Tags und Mini-Balken. mit Bewertungsdetails, Tags und Mini-Balken.
## Auswählen für Vergleich & Watchlist ## Auswählen für Vergleich & Merkliste
- Auf jeder Karte/Zeile findest du ein **Vergleichs-Icon**, mit dem du Tools zur - Auf jeder Karte/Zeile findest du ein **Vergleichs-Icon**, mit dem du Tools zur
[Vergleichsleiste](/docs/handbook/vergleichen) hinzufügst. [Vergleichsleiste](/docs/handbook/vergleichen) hinzufügst.
- Das **Lesezeichen-Icon** speichert Tools in deiner - Das **Lesezeichen-Icon** speichert Tools in deiner
[Watchlist](/docs/handbook/watchlist) (nur mit dem entsprechenden Tarif). [Merkliste](/docs/handbook/watchlist) (nur mit dem entsprechenden Tarif).
## API ## API
+10 -10
View File
@@ -1,14 +1,14 @@
--- ---
title: Watchlist title: Merkliste
order: 8 order: 8
--- ---
# Watchlist # Merkliste
Die **Watchlist** ist eine persönliche Favoritenliste. Tools darin kannst du Die **Merkliste** ist eine persönliche Favoritenliste. Tools darin kannst du
jederzeit per Klick wieder aufrufen und vergleichen. jederzeit per Klick wieder aufrufen und vergleichen.
> Die Watchlist ist ein **Premium-Feature** (Premium/Enterprise) und steht > Die Merkliste ist ein **Premium-Feature** (Premium/Enterprise) und steht
> Admins immer zur Verfügung. > Admins immer zur Verfügung.
## Voraussetzung ## Voraussetzung
@@ -21,18 +21,18 @@ beim Lesezeichen ein Hinweis auf den Tarifwechsel
- Auf jeder Karte/Zeile im Bereich **Tools durchsuchen** findest du das - Auf jeder Karte/Zeile im Bereich **Tools durchsuchen** findest du das
**Lesezeichen-Icon**. **Lesezeichen-Icon**.
- Ein Klick speichert das Tool in deiner Watchlist — das Icon wird gefüllt. - Ein Klick speichert das Tool in deiner Merkliste — das Icon wird gefüllt.
- Ein erneuter Klick entfernt es wieder. - Ein erneuter Klick entfernt es wieder.
## Watchlist ansehen ## Merkliste ansehen
Öffne die Watchlist über das Benutzermenü oder die Seitenleiste. Sie zeigt alle Öffne die Merkliste über das Benutzermenü oder die Seitenleiste. Sie zeigt alle
gespeicherten Tools als Karten. Das gefüllte Lesezeichen auf einer Karte gespeicherten Tools als Karten. Das gefüllte Lesezeichen auf einer Karte
entfernt das Tool aus der Liste. entfernt das Tool aus der Liste.
## Wo wird die Watchlist gespeichert? ## Wo wird die Merkliste gespeichert?
Die Watchlist ist eine Liste von Tool-IDs in deinen **Benutzerpräferenzen**. Die Merkliste ist eine Liste von Tool-IDs in deinen **Benutzerpräferenzen**.
Damit ist sie geräteübergreifend mit deinem Konto verbunden. Damit ist sie geräteübergreifend mit deinem Konto verbunden.
API-Referenz: [`GET /auth/me/watchlist`](/docs/reference/endpoints/auth#getMeWatchlist). API-Referenz: [`GET /auth/me/watchlist`](/docs/reference/endpoints/auth#getMeMerkliste).
+1 -1
View File
@@ -6,7 +6,7 @@
- **Vollständige Dokumentations-Site** in mkdocs-Optik unter `/docs`: - **Vollständige Dokumentations-Site** in mkdocs-Optik unter `/docs`:
- **Handbuch** mit verständlichen Erklärungen zu allen Features - **Handbuch** mit verständlichen Erklärungen zu allen Features
(Erste Schritte, Tool anlegen, Bewertungen, Vergleichen, Watchlist, (Erste Schritte, Tool anlegen, Bewertungen, Vergleichen, Merkliste,
Analytics, Administration, Datenmodell). Analytics, Administration, Datenmodell).
- **Automatisch generierte Referenz** aus `lib/api-spec/openapi.yaml`: - **Automatisch generierte Referenz** aus `lib/api-spec/openapi.yaml`:
alle Endpunkte und Datenfelder (Typ, Pflichtstatus, Constraints) — alle Endpunkte und Datenfelder (Typ, Pflichtstatus, Constraints) —
+1 -1
View File
@@ -12,7 +12,7 @@
und führt zur Standalone-Doku. und führt zur Standalone-Doku.
- **User Guide komplett überarbeitet**: 17 Handbuch-Seiten mit - **User Guide komplett überarbeitet**: 17 Handbuch-Seiten mit
Schritt-für-Schritt-Anleitungen für alle Funktionen (Tools finden, Tool Schritt-für-Schritt-Anleitungen für alle Funktionen (Tools finden, Tool
anlegen, Bewerten, Watchlist, Vergleichen, Kosten, Analytics, Pläne, anlegen, Bewerten, Merkliste, Vergleichen, Kosten, Analytics, Pläne,
Administration, Redundanz, Papierkorb, Tastenkürzel, Datenmodell). Administration, Redundanz, Papierkorb, Tastenkürzel, Datenmodell).
## Fixes & Verbesserungen ## Fixes & Verbesserungen
+1 -1
View File
@@ -10,7 +10,7 @@
(`/docs/vX.Y.Z/…`) — inklusive Handbuch und Referenz, wie sie zum (`/docs/vX.Y.Z/…`) — inklusive Handbuch und Referenz, wie sie zum
Release-Zeitpunkt galten. Die letzten 7 Versionen bleiben verfügbar. Release-Zeitpunkt galten. Die letzten 7 Versionen bleiben verfügbar.
- **Hilfe-Buttons in Formularen (NetBox-Stil)**: Bei Bewertung, Tool - **Hilfe-Buttons in Formularen (NetBox-Stil)**: Bei Bewertung, Tool
anlegen/bearbeiten, Kosten, Vergleichen, Watchlist und Analytics gibt es anlegen/bearbeiten, Kosten, Vergleichen, Merkliste und Analytics gibt es
jetzt ein Hilfe-Icon, das direkt zur passenden Anleitung im Handbuch führt. jetzt ein Hilfe-Icon, das direkt zur passenden Anleitung im Handbuch führt.
## Fixes & Verbesserungen ## Fixes & Verbesserungen
+1 -1
View File
@@ -6,7 +6,7 @@
- **Komplette Lokalisierung der App (Deutsch/Englisch)**: Alle Seiten und - **Komplette Lokalisierung der App (Deutsch/Englisch)**: Alle Seiten und
Komponenten sind jetzt übersetzt — Tool-Detailseite, Verwaltung, Papierkorb, Komponenten sind jetzt übersetzt — Tool-Detailseite, Verwaltung, Papierkorb,
Redundanz-Dashboard, Vergleichen, Watchlist, Analytics, Tool anlegen und Redundanz-Dashboard, Vergleichen, Merkliste, Analytics, Tool anlegen und
bearbeiten, Admin-Bereich inkl. Tools-Tab, Kategorie-Combobox und bearbeiten, Admin-Bereich inkl. Tools-Tab, Kategorie-Combobox und
Theme-Umschalter. Die Sprachauswahl oben rechts wechselt die gesamte Theme-Umschalter. Die Sprachauswahl oben rechts wechselt die gesamte
Oberfläche. Oberfläche.
+45
View File
@@ -0,0 +1,45 @@
# v0.8.5 — Release Notes
**Date:** 2026-08-04 · **Tag:** [`v0.8.5`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.5)
## New features
- **Help buttons across the app**: The main pages (Home, Browse tools, Trash,
Redundancy dashboard, Admin tools) as well as the premium dialog and the
password dialog now show a book icon next to the title that links directly
to the matching manual page (following the existing buttons on the tool
detail, create, edit, compare, watchlist and analytics pages).
## Fixes & improvements
- **Translated submit button when creating a tool**: The "Submit Tool" /
"Adding Tool…" button was still hardcoded and appeared in English in the
German UI. It is now translated, e.g. "Tool einreichen" / "Füge Tool
hinzu…" in German.
- **More translated UI strings**: View mode (Grid/Table/Rows), list density
(Compact/Comfortable), minimum rating in the filter and the password hint
"min. 6 characters" are now translated correctly.
- **Consistent docs terminology**: The manual now consistently calls the
watchlist "Merkliste" in all German pages and release notes; the English
version stays "Watchlist". The `watchlist` permission name and the URLs
are unchanged.
- All locales are in sync (462 keys per language, 0 missing).
## API changes
- No changes to the API.
## Operations / upgrade
- **Env vars:** unchanged.
- **Migration:** none.
- **Breaking changes:** none.
## Known limitations
- None.
## Links
- Commit: [`70e72da`](https://git.kubebase.de/admin/tool-evaluator/commit/70e72da)
- Tag: [`v0.8.5`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.5)
+46
View File
@@ -0,0 +1,46 @@
# v0.8.5 — Release Notes
**Datum:** 2026-08-04 · **Tag:** [`v0.8.5`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.5)
## Neue Features
- **Hilfe-Buttons in der gesamten App**: Auf den Hauptseiten (Start, Tools
durchsuchen, Papierkorb, Redundanz-Dashboard, Admin-Tools) sowie in
Premium-Dialog und Passwort-Dialog gibt es jetzt ein Buch-Icon neben dem
Titel, das direkt zur passenden Anleitung im Handbuch verlinkt (analog zu
den bestehenden Buttons auf Tool-Detail-, Anlegen-, Bearbeiten-,
Vergleichen-, Merkliste- und Analytics-Seiten).
## Fixes & Verbesserungen
- **Submit-Button beim Tool-Anlegen übersetzt**: Der Button „Submit Tool" /
„Adding Tool…" war noch hartkodiert und erschien auf Deutsch auf Englisch.
Jetzt: „Tool einreichen" / „Füge Tool hinzu…" (bzw. die englischen
Entsprechungen).
- **Weitere übersetzte UI-Strings**: Ansichtsmodus (Raster/Tabelle/Zeilen),
Listendichte (Kompakt/Komfortabel), Mindestbewertung im Filter sowie der
Passwort-Hinweis „min. 6 Zeichen" werden jetzt korrekt übersetzt.
- **Doku-Terminologie konsistent**: Das Handbuch heißt die Merkliste jetzt
einheitlich „Merkliste" (statt „Watchlist") in allen deutschen Seiten und
Release-Notes; die englische Fassung bleibt „Watchlist". Die
Permissions-Bezeichnung `watchlist` und die URLs sind unverändert.
- Alle Locales synchron (462 Keys pro Sprache, 0 fehlend).
## API-Änderungen
- Keine Änderungen an der API.
## Betrieb / Upgrade
- **Env-Vars:** unverändert.
- **Migration:** keine.
- **Breaking Changes:** keine.
## Bekannte Einschränkungen
- Keine.
## Links
- Commit: [`70e72da`](https://git.kubebase.de/admin/tool-evaluator/commit/70e72da)
- Tag: [`v0.8.5`](https://git.kubebase.de/admin/tool-evaluator/releases/tag/v0.8.5)