2 Commits

Author SHA1 Message Date
markmorado
aa100b49c1 docs: release notes and version bump for v1.14.0
Some checks failed
Deploy to Production / Trigger production update (push) Has been cancelled
2026-07-24 07:00:46 +05:00
markmorado
29a5d4381d fix(instances): keep workspace-scoped filters in sync with active workspace
The per-column "Node" filter memoized its option list against TanStack's
Column object, which keeps the same identity across data updates, so the
checklist stayed frozen at whatever nodes were visible when the popover
first mounted instead of reflecting the current (workspace-scoped) rows.

Switching the active workspace also left the server/node/column filters
holding values from the previous workspace, which could filter the newly
scoped VM list down to nothing.
2026-07-24 07:00:41 +05:00
5 changed files with 52 additions and 9 deletions

View File

@@ -4,6 +4,15 @@ All notable changes to PVEmanager will be documented in this file.
---
## [v1.14.0] - 2026-07-24
### 🐛 Bug Fixes
- **Workspace switch left stale instance filters behind** — the server, node and per-column filters on the Instances page kept whatever values were picked in the previously active workspace, which could filter the newly-scoped VM list down to nothing. Switching the active workspace now resets all of them
- **"Node" column filter never updated after the first render** — its checklist of available nodes was memoized against the TanStack `Column` object, which keeps the same identity across data updates, so the list stayed frozen at whatever nodes were visible when the popover first mounted — including nodes from workspaces you'd since switched away from. It now reads live from the table's faceted values on every render
---
## [v1.13.0] - 2026-07-24
### 🛒 App Store

View File

@@ -4,6 +4,15 @@
---
## [v1.14.0] - 2026-07-24
### 🐛 Исправления
- **Смена рабочей области не сбрасывала фильтры инстансов** — фильтры по серверу, узлу и столбцам на странице «Инстансы» сохраняли значения, выбранные ещё в предыдущей рабочей области, из-за чего список VM новой области мог отфильтроваться до пустоты. Теперь при переключении рабочей области все эти фильтры сбрасываются
- **Фильтр по колонке «Узел» не обновлялся после первого рендера** — список доступных узлов в нём был замемоизирован на объекте `Column` из TanStack, а этот объект сохраняет свою идентичность при обновлении данных таблицы, поэтому список замирал на тех узлах, что были видны при первом открытии — включая узлы серверов из уже покинутой рабочей области. Теперь значение читается напрямую из faceted-данных таблицы при каждом рендере
---
## [v1.13.0] - 2026-07-24
### 🛒 App Store

View File

@@ -1 +1 @@
1.13.0
1.14.0

View File

@@ -1,4 +1,3 @@
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import type { Column, FilterFn, RowData } from '@tanstack/react-table';
import { ListFilter, X } from 'lucide-react';
@@ -49,13 +48,18 @@ export function ColumnFilter<TData>({ column, variant = 'text', formatOption }:
? Array.isArray(filterValue) && filterValue.length > 0
: !!filterValue;
const uniqueValues = useMemo(() => {
if (variant !== 'select') return [];
return Array.from(column.getFacetedUniqueValues().keys())
.filter((v): v is string => v != null && String(v).length > 0)
.map(String)
.sort();
}, [variant, column]);
// Not memoized on `column` — TanStack keeps the same Column object identity
// across data updates, so a useMemo keyed on it would freeze these options
// at whatever the table's data looked like when this popover first mounted
// (e.g. before a workspace switch re-scoped the rows). getFacetedUniqueValues()
// is already memoized internally against the actual row data.
const uniqueValues =
variant === 'select'
? Array.from(column.getFacetedUniqueValues().keys())
.filter((v): v is string => v != null && String(v).length > 0)
.map(String)
.sort()
: [];
const selected = (Array.isArray(filterValue) ? filterValue : []) as string[];

View File

@@ -88,6 +88,7 @@ import { formatBytes, vmTypeLabel, formatUptime, formatVmConfig } from '@/lib/fo
import { apiClient } from '@/lib/api-client';
import { useDeployTasksStore } from '@/stores/deploy-tasks-store';
import { useBulkTasksStore } from '@/stores/bulk-tasks-store';
import { useWorkspaceStore } from '@/stores/workspace-store';
import type { VMInstance } from '@/types';
import { toast } from 'sonner';
@@ -365,6 +366,26 @@ export default function InstancesPage() {
});
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
// Reset every filter that can reference a server/node identity when the
// active workspace changes — those values belong to whatever workspace was
// active when they were picked, and silently keeping them can filter the
// new workspace's (now-scoped) VM list down to nothing.
const activeWorkspaceId = useWorkspaceStore((s) => s.activeWorkspaceId);
// Compares against the previous *value* (not a one-shot "first render" flag)
// so React 18 StrictMode's dev-only double effect invocation on mount can't
// misfire this as a real workspace change.
const prevWorkspaceIdRef = useRef(activeWorkspaceId);
useEffect(() => {
if (prevWorkspaceIdRef.current === activeWorkspaceId) return;
prevWorkspaceIdRef.current = activeWorkspaceId;
setServerFilter('all');
localStorage.setItem('instances-server-filter', 'all');
setNodeFilter('all');
localStorage.setItem('instances-node-filter', 'all');
setColumnFilters([]);
setRowSelection({});
}, [activeWorkspaceId]);
// Persist sorting + column filters across reloads
useEffect(() => {
localStorage.setItem('instances-sorting', JSON.stringify(sorting));