Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ import type {
DashboardSidebarProject,
DashboardSidebarWorkspace,
} from "./types";
import { filterDashboardSidebarProjects } from "./utils/filterDashboardSidebarProjects";
import {
filterDashboardSidebarHiddenProjects,
filterDashboardSidebarProjects,
} from "./utils/filterDashboardSidebarProjects";
import {
filterDashboardSidebarProjectsByHost,
matchesHostFilter,
Expand Down Expand Up @@ -278,8 +281,21 @@ const DashboardSidebarContent = memo(function DashboardSidebarContent({
() => displayedGroups.map((project) => project.id),
[displayedGroups],
);
const displayedHiddenProjects = useMemo(
() =>
filterDashboardSidebarHiddenProjects(hiddenProjects, projectFilterQuery),
[hiddenProjects, projectFilterQuery],
);
const trimmedFilterQuery = projectFilterQuery.trim();
const isFilterActive = trimmedFilterQuery !== "" || hostFilter !== "all";
// A matching hidden project is a match too, so the empty state would
// contradict the row above it — but only while that row is on screen, and
// only the query narrows it, never the host filter.
const hasNoMatches =
displayedGroups.length === 0 &&
(trimmedFilterQuery === "" ||
workspacesListCollapsed ||
displayedHiddenProjects.length === 0);
// The sort modes only reorder rows inside a project, so the project list
// is still the manual order and stays draggable; only a filter, which
// hides projects outright, makes a project drop unsafe to commit.
Expand Down Expand Up @@ -527,11 +543,11 @@ const DashboardSidebarContent = memo(function DashboardSidebarContent({
)}
{!isCollapsed && !workspacesListCollapsed && (
<DashboardSidebarHiddenProjects
projects={hiddenProjects}
projects={displayedHiddenProjects}
onShow={showHiddenProject}
/>
)}
{!isCollapsed && isFilterActive && displayedGroups.length === 0 && (
{!isCollapsed && isFilterActive && hasNoMatches && (
<div className="select-text cursor-text px-4 py-2 text-xs text-muted-foreground">
{trimmedFilterQuery !== ""
? t({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import {
makeSection,
makeWorkspace,
} from "../testProjectFixtures";
import { filterDashboardSidebarProjects } from "./filterDashboardSidebarProjects";
import {
filterDashboardSidebarHiddenProjects,
filterDashboardSidebarProjects,
} from "./filterDashboardSidebarProjects";

const projects = [
makeProject({
Expand Down Expand Up @@ -82,7 +85,9 @@ describe("filterDashboardSidebarProjects", () => {

it("trims the query before matching", () => {
expect(
filterDashboardSidebarProjects(projects, " hero ").map((p) => p.id),
filterDashboardSidebarProjects(projects, " hero ").map(
(project) => project.id,
),
).toEqual(["p-marketing"]);
});

Expand Down Expand Up @@ -114,3 +119,20 @@ describe("filterDashboardSidebarProjects", () => {
expect(section.section.workspaces).toHaveLength(2);
});
});

describe("filterDashboardSidebarHiddenProjects", () => {
const hidden = [
{ id: "h1", name: "premiere-plugin", iconUrl: null, color: null },
{ id: "h2", name: "nango-test", iconUrl: null, color: null },
];

it("keeps only the hidden projects whose name matches", () => {
expect(
filterDashboardSidebarHiddenProjects(hidden, "PREMIER").map((p) => p.id),
).toEqual(["h1"]);
});

it("returns the list untouched without a query", () => {
expect(filterDashboardSidebarHiddenProjects(hidden, " ")).toBe(hidden);
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {
DashboardSidebarHiddenProject,
DashboardSidebarProject,
DashboardSidebarProjectChild,
} from "../../types";
Expand Down Expand Up @@ -80,3 +81,17 @@ export function filterDashboardSidebarProjects(
return [{ ...project, isCollapsed: false, children }];
});
}

/**
* The same filter over the hidden-projects restore list, so a search still
* finds a hidden project. Names only: a hidden project's workspaces are never
* built, so there is nothing else to match.
*/
export function filterDashboardSidebarHiddenProjects(
projects: DashboardSidebarHiddenProject[],
query: string,
): DashboardSidebarHiddenProject[] {
const normalizedQuery = query.trim().toLowerCase();
if (normalizedQuery === "") return projects;
return projects.filter((project) => matches(project.name, normalizedQuery));
}
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export { filterDashboardSidebarProjects } from "./filterDashboardSidebarProjects";
export {
filterDashboardSidebarHiddenProjects,
filterDashboardSidebarProjects,
} from "./filterDashboardSidebarProjects";
Loading