Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion frontend/src/components/ui/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export default function Sidebar() {
filteredZonesMap,
filteredZoneFavorites,
filteredFileSharePathFavorites,
filteredFolderFavorites
filteredFolderFavorites,
hasResultsOutsideGroups
} = useFilteredZonesAndFavorites();

return (
Expand Down Expand Up @@ -54,6 +55,7 @@ export default function Sidebar() {
/>
<ZonesBrowser
filteredZonesMap={filteredZonesMap}
hasResultsOutsideGroups={hasResultsOutsideGroups}
searchQuery={searchQuery}
/>
</div>
Expand Down
49 changes: 43 additions & 6 deletions frontend/src/components/ui/Sidebar/ZonesBrowser.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Collapse, Typography, List } from '@material-tailwind/react';
import { HiChevronRight } from 'react-icons/hi';
import { HiSquares2X2 } from 'react-icons/hi2';
import toast from 'react-hot-toast';

import { ZonesAndFileSharePathsMap } from '@/shared.types';
import { useZoneAndFspMapContext } from '@/contexts/ZonesAndFspMapContext';
Expand All @@ -12,13 +13,15 @@ import { Link } from 'react-router';

export default function ZonesBrowser({
searchQuery,
filteredZonesMap
filteredZonesMap,
hasResultsOutsideGroups
}: {
readonly searchQuery: string;
readonly filteredZonesMap: ZonesAndFileSharePathsMap;
readonly hasResultsOutsideGroups: boolean;
}) {
const { zonesAndFspQuery } = useZoneAndFspMapContext();
const { isFilteredByGroups } = usePreferencesContext();
const { isFilteredByGroups, toggleFilterByGroups } = usePreferencesContext();
const { openZones, toggleOpenZones } = useOpenZones();

const displayZones: ZonesAndFileSharePathsMap =
Expand Down Expand Up @@ -65,11 +68,45 @@ export default function ZonesBrowser({
Object.keys(displayZones).length === 0 ? (
<div className="px-4 py-6 text-center">
<Typography className="text-sm text-foreground/60">
No zones match your filter '{searchQuery}'
</Typography>
<Typography className="text-xs text-foreground/60 mt-1">
Try broadening your search to see more results
No zones match your filter &apos;{searchQuery}&apos;
</Typography>
{hasResultsOutsideGroups ? (
<div className="mt-3 px-2 py-3 bg-surface rounded-md text-left">
<Typography className="text-xs text-foreground/70">
Results exist in Zones outside your groups.
</Typography>
<Typography className="text-xs text-foreground mt-2">
Change your zone display preferences to view:
</Typography>
<div className="flex items-center gap-2 mt-2">
<input
checked={isFilteredByGroups}
className="icon-small checked:accent-secondary-light dark:checked:accent-secondary"
id="sidebar_is_filtered_by_groups"
onChange={async () => {
const result = await toggleFilterByGroups();
if (result.success) {
toast.success('All Zones are now visible');
} else {
toast.error(result.error);
}
}}
type="checkbox"
/>
<Typography
as="label"
className="text-xs text-foreground"
htmlFor="sidebar_is_filtered_by_groups"
>
Display Zones for your groups only
</Typography>
</div>
</div>
) : (
<Typography className="text-xs text-foreground/60 mt-1">
Try broadening your search to see more results
</Typography>
)}
</div>
) : (
Object.entries(displayZones).map(([key, value]) => {
Expand Down
29 changes: 28 additions & 1 deletion frontend/src/hooks/useFilteredZonesAndFavorites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ export default function useSearchFilter() {
const [filteredFolderFavorites, setFilteredFolderFavorites] = useState<
FolderFavorite[]
>([]);
const [hasResultsOutsideGroups, setHasResultsOutsideGroups] =
useState<boolean>(false);

const filterZonesMap = useCallback(
(query: string) => {
if (!zonesAndFspQuery.isSuccess) {
setFilteredZonesMap({});
setHasResultsOutsideGroups(false);
return;
}

Expand Down Expand Up @@ -92,7 +95,28 @@ export default function useSearchFilter() {
})
.filter(Boolean); // Remove null entries

setFilteredZonesMap(Object.fromEntries(matches as [string, Zone][]));
const filteredResult = Object.fromEntries(matches as [string, Zone][]);
setFilteredZonesMap(filteredResult);

// Check if there would be results without group filtering
if (isFilteredByGroups && Object.keys(filteredResult).length === 0) {
const unfilteredMatches = Object.entries(zonesAndFspQuery.data).some(
([key, value]) => {
if (key.startsWith('zone')) {
const zone = value as Zone;
const zoneNameMatches = zone.name.toLowerCase().includes(query);
const hasMatchingFsps = zone.fileSharePaths.some(fsp =>
fsp.name.toLowerCase().includes(query)
);
return zoneNameMatches || hasMatchingFsps;
}
return false;
}
);
setHasResultsOutsideGroups(unfilteredMatches);
} else {
setHasResultsOutsideGroups(false);
}
},
[zonesAndFspQuery, isFilteredByGroups, profile]
);
Expand Down Expand Up @@ -147,6 +171,7 @@ export default function useSearchFilter() {
filterAllFavorites(searchQuery);
} else if (searchQuery === '' && isFilteredByGroups && profile?.groups) {
// When search query is empty but group filtering is enabled, apply group filter
setHasResultsOutsideGroups(false);
if (!zonesAndFspQuery.isSuccess) {
setFilteredZonesMap({});
setFilteredZoneFavorites([]);
Expand Down Expand Up @@ -189,6 +214,7 @@ export default function useSearchFilter() {
setFilteredZoneFavorites([]);
setFilteredFileSharePathFavorites([]);
setFilteredFolderFavorites([]);
setHasResultsOutsideGroups(false);
}
}, [
searchQuery,
Expand All @@ -208,6 +234,7 @@ export default function useSearchFilter() {
filteredZoneFavorites,
filteredFileSharePathFavorites,
filteredFolderFavorites,
hasResultsOutsideGroups,
handleSearchChange,
clearSearch
};
Expand Down
Loading