Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d47db6d386 | |||
| 70e72dac71 |
@@ -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, labelKey, Icon }) => (
|
||||||
|
<ToggleGroupItem
|
||||||
|
key={v}
|
||||||
|
value={v}
|
||||||
|
aria-label={t(labelKey)}
|
||||||
|
title={t(labelKey)}
|
||||||
|
data-testid={`view-${v}`}
|
||||||
>
|
>
|
||||||
{OPTIONS.map(({ value: v, label, Icon }) => (
|
|
||||||
<ToggleGroupItem key={v} value={v} aria-label={label} title={label} data-testid={`view-${v}`}>
|
|
||||||
<Icon className="w-4 h-4" />
|
<Icon className="w-4 h-4" />
|
||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -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",
|
||||||
@@ -55,7 +56,15 @@
|
|||||||
"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",
|
||||||
|
|||||||
@@ -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",
|
||||||
@@ -55,7 +56,15 @@
|
|||||||
"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",
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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")}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 (1–5) plus Kommentar vergeben | Angemeldet |
|
| **Bewerten** | Nützlichkeit & Bedienbarkeit (1–5) 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 |
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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) |
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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).
|
||||||
|
|||||||
@@ -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) —
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -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)
|
||||||
Reference in New Issue
Block a user