Compare commits
1 Commits
MickLesk-p
...
fix/320
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff26c54c44 |
@@ -10,6 +10,7 @@ import { FilterBar, type FilterState } from './FilterBar';
|
|||||||
import { ViewToggle } from './ViewToggle';
|
import { ViewToggle } from './ViewToggle';
|
||||||
import { Button } from './ui/button';
|
import { Button } from './ui/button';
|
||||||
import type { ScriptCard as ScriptCardType } from '~/types/script';
|
import type { ScriptCard as ScriptCardType } from '~/types/script';
|
||||||
|
import { getDefaultFilters, mergeFiltersWithDefaults } from './filterUtils';
|
||||||
|
|
||||||
interface DownloadedScriptsTabProps {
|
interface DownloadedScriptsTabProps {
|
||||||
onInstallScript?: (
|
onInstallScript?: (
|
||||||
@@ -25,14 +26,7 @@ export function DownloadedScriptsTab({ onInstallScript }: DownloadedScriptsTabPr
|
|||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
|
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
|
||||||
const [viewMode, setViewMode] = useState<'card' | 'list'>('card');
|
const [viewMode, setViewMode] = useState<'card' | 'list'>('card');
|
||||||
const [filters, setFilters] = useState<FilterState>({
|
const [filters, setFilters] = useState<FilterState>(getDefaultFilters());
|
||||||
searchQuery: '',
|
|
||||||
showUpdatable: null,
|
|
||||||
selectedTypes: [],
|
|
||||||
selectedRepositories: [],
|
|
||||||
sortBy: 'name',
|
|
||||||
sortOrder: 'asc',
|
|
||||||
});
|
|
||||||
const [saveFiltersEnabled, setSaveFiltersEnabled] = useState(false);
|
const [saveFiltersEnabled, setSaveFiltersEnabled] = useState(false);
|
||||||
const [isLoadingFilters, setIsLoadingFilters] = useState(true);
|
const [isLoadingFilters, setIsLoadingFilters] = useState(true);
|
||||||
const gridRef = useRef<HTMLDivElement>(null);
|
const gridRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -63,7 +57,7 @@ export function DownloadedScriptsTab({ onInstallScript }: DownloadedScriptsTabPr
|
|||||||
if (filtersResponse.ok) {
|
if (filtersResponse.ok) {
|
||||||
const filtersData = await filtersResponse.json();
|
const filtersData = await filtersResponse.json();
|
||||||
if (filtersData.filters) {
|
if (filtersData.filters) {
|
||||||
setFilters(filtersData.filters as FilterState);
|
setFilters(mergeFiltersWithDefaults(filtersData.filters));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Button } from "./ui/button";
|
|||||||
import { ContextualHelpIcon } from "./ContextualHelpIcon";
|
import { ContextualHelpIcon } from "./ContextualHelpIcon";
|
||||||
import { Package, Monitor, Wrench, Server, FileText, Calendar, RefreshCw, Filter, GitBranch } from "lucide-react";
|
import { Package, Monitor, Wrench, Server, FileText, Calendar, RefreshCw, Filter, GitBranch } from "lucide-react";
|
||||||
import { api } from "~/trpc/react";
|
import { api } from "~/trpc/react";
|
||||||
|
import { getDefaultFilters } from "./filterUtils";
|
||||||
|
|
||||||
export interface FilterState {
|
export interface FilterState {
|
||||||
searchQuery: string;
|
searchQuery: string;
|
||||||
@@ -67,14 +68,7 @@ export function FilterBar({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const clearAllFilters = () => {
|
const clearAllFilters = () => {
|
||||||
onFiltersChange({
|
onFiltersChange(getDefaultFilters());
|
||||||
searchQuery: "",
|
|
||||||
showUpdatable: null,
|
|
||||||
selectedTypes: [],
|
|
||||||
selectedRepositories: [],
|
|
||||||
sortBy: "name",
|
|
||||||
sortOrder: "asc",
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasActiveFilters =
|
const hasActiveFilters =
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { ViewToggle } from './ViewToggle';
|
|||||||
import { Button } from './ui/button';
|
import { Button } from './ui/button';
|
||||||
import { Clock } from 'lucide-react';
|
import { Clock } from 'lucide-react';
|
||||||
import type { ScriptCard as ScriptCardType } from '~/types/script';
|
import type { ScriptCard as ScriptCardType } from '~/types/script';
|
||||||
|
import { getDefaultFilters, mergeFiltersWithDefaults } from './filterUtils';
|
||||||
|
|
||||||
|
|
||||||
interface ScriptsGridProps {
|
interface ScriptsGridProps {
|
||||||
@@ -25,14 +26,7 @@ export function ScriptsGrid({ onInstallScript }: ScriptsGridProps) {
|
|||||||
const [viewMode, setViewMode] = useState<'card' | 'list'>('card');
|
const [viewMode, setViewMode] = useState<'card' | 'list'>('card');
|
||||||
const [selectedSlugs, setSelectedSlugs] = useState<Set<string>>(new Set());
|
const [selectedSlugs, setSelectedSlugs] = useState<Set<string>>(new Set());
|
||||||
const [downloadProgress, setDownloadProgress] = useState<{ current: number; total: number; currentScript: string; failed: Array<{ slug: string; error: string }> } | null>(null);
|
const [downloadProgress, setDownloadProgress] = useState<{ current: number; total: number; currentScript: string; failed: Array<{ slug: string; error: string }> } | null>(null);
|
||||||
const [filters, setFilters] = useState<FilterState>({
|
const [filters, setFilters] = useState<FilterState>(getDefaultFilters());
|
||||||
searchQuery: '',
|
|
||||||
showUpdatable: null,
|
|
||||||
selectedTypes: [],
|
|
||||||
selectedRepositories: [],
|
|
||||||
sortBy: 'name',
|
|
||||||
sortOrder: 'asc',
|
|
||||||
});
|
|
||||||
const [saveFiltersEnabled, setSaveFiltersEnabled] = useState(false);
|
const [saveFiltersEnabled, setSaveFiltersEnabled] = useState(false);
|
||||||
const [isLoadingFilters, setIsLoadingFilters] = useState(true);
|
const [isLoadingFilters, setIsLoadingFilters] = useState(true);
|
||||||
const [isNewestMinimized, setIsNewestMinimized] = useState(false);
|
const [isNewestMinimized, setIsNewestMinimized] = useState(false);
|
||||||
@@ -67,7 +61,7 @@ export function ScriptsGrid({ onInstallScript }: ScriptsGridProps) {
|
|||||||
if (filtersResponse.ok) {
|
if (filtersResponse.ok) {
|
||||||
const filtersData = await filtersResponse.json();
|
const filtersData = await filtersResponse.json();
|
||||||
if (filtersData.filters) {
|
if (filtersData.filters) {
|
||||||
setFilters(filtersData.filters as FilterState);
|
setFilters(mergeFiltersWithDefaults(filtersData.filters));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
44
src/app/_components/filterUtils.ts
Normal file
44
src/app/_components/filterUtils.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import type { FilterState } from "./FilterBar";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default FilterState with all properties initialized.
|
||||||
|
* This serves as the single source of truth for default filter values.
|
||||||
|
*/
|
||||||
|
export function getDefaultFilters(): FilterState {
|
||||||
|
return {
|
||||||
|
searchQuery: "",
|
||||||
|
showUpdatable: null,
|
||||||
|
selectedTypes: [],
|
||||||
|
selectedRepositories: [],
|
||||||
|
sortBy: "name",
|
||||||
|
sortOrder: "asc",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges saved filters with defaults, ensuring all FilterState properties exist.
|
||||||
|
* This prevents crashes when loading old saved filters that are missing new properties.
|
||||||
|
*
|
||||||
|
* @param savedFilters - Partial or undefined saved filters from storage
|
||||||
|
* @returns Complete FilterState with all properties guaranteed to exist
|
||||||
|
*/
|
||||||
|
export function mergeFiltersWithDefaults(
|
||||||
|
savedFilters: Partial<FilterState> | undefined
|
||||||
|
): FilterState {
|
||||||
|
const defaults = getDefaultFilters();
|
||||||
|
|
||||||
|
if (!savedFilters) {
|
||||||
|
return defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge saved filters with defaults, ensuring all properties exist
|
||||||
|
return {
|
||||||
|
searchQuery: savedFilters.searchQuery ?? defaults.searchQuery,
|
||||||
|
showUpdatable: savedFilters.showUpdatable ?? defaults.showUpdatable,
|
||||||
|
selectedTypes: savedFilters.selectedTypes ?? defaults.selectedTypes,
|
||||||
|
selectedRepositories: savedFilters.selectedRepositories ?? defaults.selectedRepositories,
|
||||||
|
sortBy: savedFilters.sortBy ?? defaults.sortBy,
|
||||||
|
sortOrder: savedFilters.sortOrder ?? defaults.sortOrder,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user