Browse Source

Filter & Search Workspace Task History (#2526)

* Enhancement: Add 'Show all workspaces' feature to task history and update translations

* Enhancement: Add Checkbox component and integrate it into HistoryPreview and HistoryView

* Simplify the UX

---------

Co-authored-by: Matt Rubens <[email protected]>
Sam Hoang Van 8 months ago
parent
commit
08110ae35b

+ 213 - 0
webview-ui/package-lock.json

@@ -9,6 +9,7 @@
 			"version": "0.1.0",
 			"dependencies": {
 				"@radix-ui/react-alert-dialog": "^1.1.6",
+				"@radix-ui/react-checkbox": "^1.1.5",
 				"@radix-ui/react-collapsible": "^1.1.3",
 				"@radix-ui/react-dialog": "^1.1.6",
 				"@radix-ui/react-dropdown-menu": "^2.1.5",
@@ -3851,6 +3852,218 @@
 				}
 			}
 		},
+		"node_modules/@radix-ui/react-checkbox": {
+			"version": "1.1.5",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.5.tgz",
+			"integrity": "sha512-B0gYIVxl77KYDR25AY9EGe/G//ef85RVBIxQvK+m5pxAC7XihAc/8leMHhDvjvhDu02SBSb6BuytlWr/G7F3+g==",
+			"license": "MIT",
+			"dependencies": {
+				"@radix-ui/primitive": "1.1.2",
+				"@radix-ui/react-compose-refs": "1.1.2",
+				"@radix-ui/react-context": "1.1.2",
+				"@radix-ui/react-presence": "1.1.3",
+				"@radix-ui/react-primitive": "2.0.3",
+				"@radix-ui/react-use-controllable-state": "1.1.1",
+				"@radix-ui/react-use-previous": "1.1.1",
+				"@radix-ui/react-use-size": "1.1.1"
+			},
+			"peerDependencies": {
+				"@types/react": "*",
+				"@types/react-dom": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+				"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				},
+				"@types/react-dom": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/primitive": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz",
+			"integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==",
+			"license": "MIT"
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-compose-refs": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+			"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+			"license": "MIT",
+			"peerDependencies": {
+				"@types/react": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-context": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+			"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+			"license": "MIT",
+			"peerDependencies": {
+				"@types/react": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-presence": {
+			"version": "1.1.3",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.3.tgz",
+			"integrity": "sha512-IrVLIhskYhH3nLvtcBLQFZr61tBG7wx7O3kEmdzcYwRGAEBmBicGGL7ATzNgruYJ3xBTbuzEEq9OXJM3PAX3tA==",
+			"license": "MIT",
+			"dependencies": {
+				"@radix-ui/react-compose-refs": "1.1.2",
+				"@radix-ui/react-use-layout-effect": "1.1.1"
+			},
+			"peerDependencies": {
+				"@types/react": "*",
+				"@types/react-dom": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+				"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				},
+				"@types/react-dom": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": {
+			"version": "2.0.3",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.3.tgz",
+			"integrity": "sha512-Pf/t/GkndH7CQ8wE2hbkXA+WyZ83fhQQn5DDmwDiDo6AwN/fhaH8oqZ0jRjMrO2iaMhDi6P1HRx6AZwyMinY1g==",
+			"license": "MIT",
+			"dependencies": {
+				"@radix-ui/react-slot": "1.2.0"
+			},
+			"peerDependencies": {
+				"@types/react": "*",
+				"@types/react-dom": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+				"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				},
+				"@types/react-dom": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": {
+			"version": "1.2.0",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz",
+			"integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==",
+			"license": "MIT",
+			"dependencies": {
+				"@radix-ui/react-compose-refs": "1.1.2"
+			},
+			"peerDependencies": {
+				"@types/react": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-callback-ref": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+			"integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+			"license": "MIT",
+			"peerDependencies": {
+				"@types/react": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-controllable-state": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.1.tgz",
+			"integrity": "sha512-YnEXIy8/ga01Y1PN0VfaNH//MhA91JlEGVBDxDzROqwrAtG5Yr2QGEPz8A/rJA3C7ZAHryOYGaUv8fLSW2H/mg==",
+			"license": "MIT",
+			"dependencies": {
+				"@radix-ui/react-use-callback-ref": "1.1.1"
+			},
+			"peerDependencies": {
+				"@types/react": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-layout-effect": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+			"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+			"license": "MIT",
+			"peerDependencies": {
+				"@types/react": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-previous": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
+			"integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
+			"license": "MIT",
+			"peerDependencies": {
+				"@types/react": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-size": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+			"integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+			"license": "MIT",
+			"dependencies": {
+				"@radix-ui/react-use-layout-effect": "1.1.1"
+			},
+			"peerDependencies": {
+				"@types/react": "*",
+				"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+			},
+			"peerDependenciesMeta": {
+				"@types/react": {
+					"optional": true
+				}
+			}
+		},
 		"node_modules/@radix-ui/react-collapsible": {
 			"version": "1.1.3",
 			"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.3.tgz",

+ 1 - 0
webview-ui/package.json

@@ -19,6 +19,7 @@
 	},
 	"dependencies": {
 		"@radix-ui/react-alert-dialog": "^1.1.6",
+		"@radix-ui/react-checkbox": "^1.1.5",
 		"@radix-ui/react-collapsible": "^1.1.3",
 		"@radix-ui/react-dialog": "^1.1.6",
 		"@radix-ui/react-dropdown-menu": "^2.1.5",

+ 3 - 3
webview-ui/src/components/history/HistoryPreview.tsx

@@ -4,15 +4,15 @@ import { vscode } from "@/utils/vscode"
 import { formatLargeNumber, formatDate } from "@/utils/format"
 import { Button } from "@/components/ui"
 
-import { useExtensionState } from "../../context/ExtensionStateContext"
 import { useAppTranslation } from "../../i18n/TranslationContext"
 import { CopyButton } from "./CopyButton"
+import { useTaskSearch } from "./useTaskSearch"
 
 type HistoryPreviewProps = {
 	showHistoryView: () => void
 }
 const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
-	const { taskHistory } = useExtensionState()
+	const { tasks } = useTaskSearch()
 	const { t } = useAppTranslation()
 
 	return (
@@ -26,7 +26,7 @@ const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
 					{t("history:viewAll")}
 				</Button>
 			</div>
-			{taskHistory.slice(0, 3).map((item) => (
+			{tasks.slice(0, 3).map((item) => (
 				<div
 					key={item.id}
 					className="bg-vscode-toolbar-hoverBackground/50 hover:bg-vscode-toolbar-hoverBackground/75 rounded-xs relative overflow-hidden opacity-90 hover:opacity-100 cursor-pointer"

+ 50 - 18
webview-ui/src/components/history/HistoryView.tsx

@@ -4,12 +4,12 @@ import { BatchDeleteTaskDialog } from "./BatchDeleteTaskDialog"
 import prettyBytes from "pretty-bytes"
 import { Virtuoso } from "react-virtuoso"
 
-import { VSCodeTextField, VSCodeRadioGroup, VSCodeRadio, VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
+import { VSCodeTextField, VSCodeRadioGroup, VSCodeRadio } from "@vscode/webview-ui-toolkit/react"
 
 import { vscode } from "@/utils/vscode"
 import { formatLargeNumber, formatDate } from "@/utils/format"
 import { cn } from "@/lib/utils"
-import { Button } from "@/components/ui"
+import { Button, Checkbox } from "@/components/ui"
 import { useAppTranslation } from "@/i18n/TranslationContext"
 
 import { Tab, TabContent, TabHeader } from "../common/Tab"
@@ -24,7 +24,16 @@ type HistoryViewProps = {
 type SortOption = "newest" | "oldest" | "mostExpensive" | "mostTokens" | "mostRelevant"
 
 const HistoryView = ({ onDone }: HistoryViewProps) => {
-	const { tasks, searchQuery, setSearchQuery, sortOption, setSortOption, setLastNonRelevantSort } = useTaskSearch()
+	const {
+		tasks,
+		searchQuery,
+		setSearchQuery,
+		sortOption,
+		setSortOption,
+		setLastNonRelevantSort,
+		showAllWorkspaces,
+		setShowAllWorkspaces,
+	} = useTaskSearch()
 	const { t } = useAppTranslation()
 
 	const [deleteTaskId, setDeleteTaskId] = useState<string | null>(null)
@@ -147,21 +156,36 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
 						</VSCodeRadio>
 					</VSCodeRadioGroup>
 
+					<div className="flex items-center gap-2" onClick={() => setShowAllWorkspaces(!showAllWorkspaces)}>
+						<Checkbox
+							checked={showAllWorkspaces}
+							onCheckedChange={(checked) => setShowAllWorkspaces(checked === true)}
+							variant="description"
+						/>
+						<span className="text-vscode-foreground">{t("history:showAllWorkspaces")}</span>
+					</div>
+
 					{/* Select all control in selection mode */}
 					{isSelectionMode && tasks.length > 0 && (
 						<div className="flex items-center py-1 px-2 bg-vscode-editor-background rounded">
-							<VSCodeCheckbox
-								checked={tasks.length > 0 && selectedTaskIds.length === tasks.length}
-								onChange={(e) => toggleSelectAll((e.target as HTMLInputElement).checked)}
-							/>
-							<span className="ml-2 text-vscode-foreground">
-								{selectedTaskIds.length === tasks.length
-									? t("history:deselectAll")
-									: t("history:selectAll")}
-							</span>
-							<span className="ml-auto text-vscode-descriptionForeground text-xs">
-								{t("history:selectedItems", { selected: selectedTaskIds.length, total: tasks.length })}
-							</span>
+							<div className="flex items-center gap-2">
+								<Checkbox
+									checked={tasks.length > 0 && selectedTaskIds.length === tasks.length}
+									onCheckedChange={(checked) => toggleSelectAll(checked === true)}
+									variant="description"
+								/>
+								<span className="text-vscode-foreground">
+									{selectedTaskIds.length === tasks.length
+										? t("history:deselectAll")
+										: t("history:selectAll")}
+								</span>
+								<span className="ml-auto text-vscode-descriptionForeground text-xs">
+									{t("history:selectedItems", {
+										selected: selectedTaskIds.length,
+										total: tasks.length,
+									})}
+								</span>
+							</div>
 						</div>
 					)}
 				</div>
@@ -203,11 +227,12 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
 										onClick={(e) => {
 											e.stopPropagation()
 										}}>
-										<VSCodeCheckbox
+										<Checkbox
 											checked={selectedTaskIds.includes(item.id)}
-											onChange={(e) =>
-												toggleTaskSelection(item.id, (e.target as HTMLInputElement).checked)
+											onCheckedChange={(checked) =>
+												toggleTaskSelection(item.id, checked === true)
 											}
+											variant="description"
 										/>
 									</div>
 								)}
@@ -407,6 +432,13 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
 												)}
 											</div>
 										)}
+
+										{showAllWorkspaces && item.workspace && (
+											<div className="flex flex-row gap-1 text-vscode-descriptionForeground text-xs">
+												<span className="codicon codicon-folder scale-80" />
+												<span>{item.workspace}</span>
+											</div>
+										)}
 									</div>
 								</div>
 							</div>

+ 25 - 11
webview-ui/src/components/history/useTaskSearch.ts

@@ -7,10 +7,11 @@ import { useExtensionState } from "@/context/ExtensionStateContext"
 type SortOption = "newest" | "oldest" | "mostExpensive" | "mostTokens" | "mostRelevant"
 
 export const useTaskSearch = () => {
-	const { taskHistory } = useExtensionState()
+	const { taskHistory, cwd } = useExtensionState()
 	const [searchQuery, setSearchQuery] = useState("")
 	const [sortOption, setSortOption] = useState<SortOption>("newest")
 	const [lastNonRelevantSort, setLastNonRelevantSort] = useState<SortOption | null>("newest")
+	const [showAllWorkspaces, setShowAllWorkspaces] = useState(false)
 
 	useEffect(() => {
 		if (searchQuery && sortOption !== "mostRelevant" && !lastNonRelevantSort) {
@@ -23,8 +24,12 @@ export const useTaskSearch = () => {
 	}, [searchQuery, sortOption, lastNonRelevantSort])
 
 	const presentableTasks = useMemo(() => {
-		return taskHistory.filter((item) => item.ts && item.task)
-	}, [taskHistory])
+		let tasks = taskHistory.filter((item) => item.ts && item.task)
+		if (!showAllWorkspaces) {
+			tasks = tasks.filter((item) => item.workspace === cwd)
+		}
+		return tasks
+	}, [taskHistory, showAllWorkspaces, cwd])
 
 	const fzf = useMemo(() => {
 		return new Fzf(presentableTasks, {
@@ -34,19 +39,26 @@ export const useTaskSearch = () => {
 
 	const tasks = useMemo(() => {
 		let results = presentableTasks
+
 		if (searchQuery) {
 			const searchResults = fzf.find(searchQuery)
-			results = searchResults.map((result) => ({
-				...result.item,
-				task: highlightFzfMatch(result.item.task, Array.from(result.positions)),
-			}))
-		}
+			results = searchResults.map((result) => {
+				const positions = Array.from(result.positions)
+				const taskEndIndex = result.item.task.length
 
-		// First apply search if needed
-		const searchResults = searchQuery ? results : presentableTasks
+				return {
+					...result.item,
+					task: highlightFzfMatch(
+						result.item.task,
+						positions.filter((p) => p < taskEndIndex),
+					),
+					workspace: result.item.workspace,
+				}
+			})
+		}
 
 		// Then sort the results
-		return [...searchResults].sort((a, b) => {
+		return [...results].sort((a, b) => {
 			switch (sortOption) {
 				case "oldest":
 					return (a.ts || 0) - (b.ts || 0)
@@ -74,5 +86,7 @@ export const useTaskSearch = () => {
 		setSortOption,
 		lastNonRelevantSort,
 		setLastNonRelevantSort,
+		showAllWorkspaces,
+		setShowAllWorkspaces,
 	}
 }

+ 42 - 0
webview-ui/src/components/ui/checkbox.tsx

@@ -0,0 +1,42 @@
+"use client"
+
+import * as React from "react"
+import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
+import { Check } from "lucide-react"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils"
+
+const checkboxVariants = cva(
+	"peer h-4 w-4 shrink-0 rounded-sm border ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
+	{
+		variants: {
+			variant: {
+				default:
+					"border-vscode-foreground data-[state=checked]:bg-vscode-foreground data-[state=checked]:text-primary-foreground",
+				description:
+					"border-vscode-descriptionForeground data-[state=checked]:bg-vscode-descriptionForeground data-[state=checked]:text-white",
+			},
+		},
+		defaultVariants: {
+			variant: "default",
+		},
+	},
+)
+
+export interface CheckboxProps
+	extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>,
+		VariantProps<typeof checkboxVariants> {}
+
+const Checkbox = React.forwardRef<React.ElementRef<typeof CheckboxPrimitive.Root>, CheckboxProps>(
+	({ className, variant, ...props }, ref) => (
+		<CheckboxPrimitive.Root ref={ref} className={cn(checkboxVariants({ variant, className }))} {...props}>
+			<CheckboxPrimitive.Indicator className={cn("flex items-center justify-center text-current")}>
+				<Check className="h-4 w-4 text-vscode-background" />
+			</CheckboxPrimitive.Indicator>
+		</CheckboxPrimitive.Root>
+	),
+)
+Checkbox.displayName = CheckboxPrimitive.Root.displayName
+
+export { Checkbox, checkboxVariants }

+ 1 - 0
webview-ui/src/components/ui/index.ts

@@ -2,6 +2,7 @@ export * from "./alert-dialog"
 export * from "./autosize-textarea"
 export * from "./badge"
 export * from "./button"
+export * from "./checkbox"
 export * from "./collapsible"
 export * from "./command"
 export * from "./dialog"

+ 2 - 1
webview-ui/src/i18n/locales/ca/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Eliminar tasques",
 	"confirmDeleteTasks": "Estàs segur que vols eliminar {{count}} tasques?",
 	"deleteTasksWarning": "Les tasques eliminades no es poden recuperar. Si us plau, assegura't que vols continuar.",
-	"deleteItems": "Eliminar {{count}} elements"
+	"deleteItems": "Eliminar {{count}} elements",
+	"showAllWorkspaces": "Mostrar tasques de tots els espais de treball"
 }

+ 2 - 1
webview-ui/src/i18n/locales/de/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Aufgaben löschen",
 	"confirmDeleteTasks": "Bist du sicher, dass du {{count}} Aufgaben löschen möchtest?",
 	"deleteTasksWarning": "Gelöschte Aufgaben können nicht wiederhergestellt werden. Bitte vergewissere dich, dass du fortfahren möchtest.",
-	"deleteItems": "{{count}} Elemente löschen"
+	"deleteItems": "{{count}} Elemente löschen",
+	"showAllWorkspaces": "Aufgaben aus allen Arbeitsbereichen anzeigen"
 }

+ 2 - 1
webview-ui/src/i18n/locales/en/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Delete Tasks",
 	"confirmDeleteTasks": "Are you sure you want to delete {{count}} tasks?",
 	"deleteTasksWarning": "Deleted tasks cannot be recovered. Please make sure you want to proceed.",
-	"deleteItems": "Delete {{count}} Items"
+	"deleteItems": "Delete {{count}} Items",
+	"showAllWorkspaces": "Show tasks from all workspaces"
 }

+ 2 - 1
webview-ui/src/i18n/locales/es/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Eliminar tareas",
 	"confirmDeleteTasks": "¿Estás seguro de que quieres eliminar {{count}} tareas?",
 	"deleteTasksWarning": "Las tareas eliminadas no se pueden recuperar. Por favor, asegúrate de que quieres continuar.",
-	"deleteItems": "Eliminar {{count}} elementos"
+	"deleteItems": "Eliminar {{count}} elementos",
+	"showAllWorkspaces": "Mostrar tareas de todos los espacios de trabajo"
 }

+ 2 - 1
webview-ui/src/i18n/locales/fr/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Supprimer les tâches",
 	"confirmDeleteTasks": "Êtes-vous sûr de vouloir supprimer {{count}} tâches ?",
 	"deleteTasksWarning": "Les tâches supprimées ne peuvent pas être récupérées. Veuillez confirmer que vous souhaitez continuer.",
-	"deleteItems": "Supprimer {{count}} éléments"
+	"deleteItems": "Supprimer {{count}} éléments",
+	"showAllWorkspaces": "Afficher les tâches de tous les espaces de travail"
 }

+ 2 - 1
webview-ui/src/i18n/locales/hi/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "कार्य हटाएं",
 	"confirmDeleteTasks": "क्या आप वाकई {{count}} कार्य हटाना चाहते हैं?",
 	"deleteTasksWarning": "हटाए गए कार्य पुनर्प्राप्त नहीं किए जा सकते। कृपया सुनिश्चित करें कि आप आगे बढ़ना चाहते हैं।",
-	"deleteItems": "{{count}} आइटम हटाएं"
+	"deleteItems": "{{count}} आइटम हटाएं",
+	"showAllWorkspaces": "सभी वर्कस्पेस से कार्य दिखाएं"
 }

+ 2 - 1
webview-ui/src/i18n/locales/it/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Elimina attività",
 	"confirmDeleteTasks": "Sei sicuro di voler eliminare {{count}} attività?",
 	"deleteTasksWarning": "Le attività eliminate non possono essere recuperate. Assicurati di voler continuare.",
-	"deleteItems": "Elimina {{count}} elementi"
+	"deleteItems": "Elimina {{count}} elementi",
+	"showAllWorkspaces": "Mostra attività da tutti gli spazi di lavoro"
 }

+ 2 - 1
webview-ui/src/i18n/locales/ja/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "タスクを削除",
 	"confirmDeleteTasks": "{{count}} 件のタスクを削除してもよろしいですか?",
 	"deleteTasksWarning": "削除されたタスクは復元できません。続行してもよろしいですか?",
-	"deleteItems": "{{count}} 項目を削除"
+	"deleteItems": "{{count}} 項目を削除",
+	"showAllWorkspaces": "すべてのワークスペースのタスクを表示"
 }

+ 2 - 1
webview-ui/src/i18n/locales/ko/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "작업 삭제",
 	"confirmDeleteTasks": "{{count}}개의 작업을 삭제하시겠습니까?",
 	"deleteTasksWarning": "삭제된 작업은 복구할 수 없습니다. 계속 진행하시겠습니까?",
-	"deleteItems": "{{count}}개 항목 삭제"
+	"deleteItems": "{{count}}개 항목 삭제",
+	"showAllWorkspaces": "모든 워크스페이스의 작업 표시"
 }

+ 2 - 1
webview-ui/src/i18n/locales/pl/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Usuń zadania",
 	"confirmDeleteTasks": "Czy na pewno chcesz usunąć {{count}} zadań?",
 	"deleteTasksWarning": "Usuniętych zadań nie można przywrócić. Upewnij się, że chcesz kontynuować.",
-	"deleteItems": "Usuń {{count}} elementów"
+	"deleteItems": "Usuń {{count}} elementów",
+	"showAllWorkspaces": "Pokaż zadania ze wszystkich przestrzeni roboczych"
 }

+ 2 - 1
webview-ui/src/i18n/locales/pt-BR/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Excluir tarefas",
 	"confirmDeleteTasks": "Tem certeza que deseja excluir {{count}} tarefas?",
 	"deleteTasksWarning": "As tarefas excluídas não podem ser recuperadas. Por favor, certifique-se de que deseja prosseguir.",
-	"deleteItems": "Excluir {{count}} itens"
+	"deleteItems": "Excluir {{count}} itens",
+	"showAllWorkspaces": "Mostrar tarefas de todos os espaços de trabalho"
 }

+ 2 - 1
webview-ui/src/i18n/locales/tr/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Görevleri Sil",
 	"confirmDeleteTasks": "{{count}} görevi silmek istediğinizden emin misiniz?",
 	"deleteTasksWarning": "Silinen görevler geri alınamaz. Lütfen devam etmek istediğinizden emin olun.",
-	"deleteItems": "{{count}} Öğeyi Sil"
+	"deleteItems": "{{count}} Öğeyi Sil",
+	"showAllWorkspaces": "Tüm çalışma alanlarından görevleri göster"
 }

+ 2 - 1
webview-ui/src/i18n/locales/vi/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "Xóa nhiệm vụ",
 	"confirmDeleteTasks": "Bạn có chắc chắn muốn xóa {{count}} nhiệm vụ không?",
 	"deleteTasksWarning": "Các nhiệm vụ đã xóa không thể khôi phục. Vui lòng chắc chắn bạn muốn tiếp tục.",
-	"deleteItems": "Xóa {{count}} mục"
+	"deleteItems": "Xóa {{count}} mục",
+	"showAllWorkspaces": "Hiển thị nhiệm vụ từ tất cả không gian làm việc"
 }

+ 2 - 1
webview-ui/src/i18n/locales/zh-CN/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "删除任务",
 	"confirmDeleteTasks": "确认删除 {{count}} 项任务?",
 	"deleteTasksWarning": "删除后将无法恢复,请谨慎操作。",
-	"deleteItems": "删除 {{count}} 项"
+	"deleteItems": "删除 {{count}} 项",
+	"showAllWorkspaces": "显示所有工作区的任务"
 }

+ 2 - 1
webview-ui/src/i18n/locales/zh-TW/history.json

@@ -34,5 +34,6 @@
 	"deleteTasks": "刪除工作",
 	"confirmDeleteTasks": "確定要刪除 {{count}} 個工作嗎?",
 	"deleteTasksWarning": "已刪除的工作無法還原。請確認是否要繼續。",
-	"deleteItems": "刪除 {{count}} 個項目"
+	"deleteItems": "刪除 {{count}} 個項目",
+	"showAllWorkspaces": "顯示所有工作區的工作"
 }