Skip to content

Commit 3ed341e

Browse files
committed
refactor: remove usercomponents from componentLibraryProvider
1 parent c1bd3e3 commit 3ed341e

File tree

11 files changed

+130
-743
lines changed

11 files changed

+130
-743
lines changed

src/components/shared/Dialogs/ComponentDetailsDialog.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useSuspenseQuery } from "@tanstack/react-query";
12
import { Code, InfoIcon, ListFilter } from "lucide-react";
23
import { type ReactNode, useCallback, useMemo, useState } from "react";
34

@@ -13,7 +14,8 @@ import { Icon } from "@/components/ui/icon";
1314
import { BlockStack, InlineStack } from "@/components/ui/layout";
1415
import { Skeleton } from "@/components/ui/skeleton";
1516
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
16-
import { useHydrateComponentReference } from "@/hooks/useHydrateComponentReference";
17+
import { useGuaranteedHydrateComponentReference } from "@/hooks/useHydrateComponentReference";
18+
import { useComponentLibrary } from "@/providers/ComponentLibraryProvider/ComponentLibraryProvider";
1719
import type { ComponentReference } from "@/utils/componentSpec";
1820

1921
import InfoIconButton from "../Buttons/InfoIconButton";
@@ -74,7 +76,14 @@ const ComponentDetailsDialogContent = withSuspenseWrapper(
7476
"remote-component-library-search",
7577
);
7678

77-
const componentRef = useHydrateComponentReference(component);
79+
const componentRef = useGuaranteedHydrateComponentReference(component);
80+
const { getComponentLibrary } = useComponentLibrary();
81+
const userComponentsLibrary = getComponentLibrary("user_components");
82+
83+
const { data: isUserComponent } = useSuspenseQuery({
84+
queryKey: ["is-user-component", componentRef.digest],
85+
queryFn: () => userComponentsLibrary.hasComponent(componentRef),
86+
});
7887

7988
if (!componentRef) {
8089
return (
@@ -87,7 +96,7 @@ const ComponentDetailsDialogContent = withSuspenseWrapper(
8796
const { url, spec: componentSpec, digest: componentDigest } = componentRef;
8897

8998
const hasPublishSection =
90-
remoteComponentLibrarySearchEnabled && component.owned;
99+
remoteComponentLibrarySearchEnabled && isUserComponent;
91100

92101
return (
93102
<>

src/components/shared/Dialogs/ComponentDuplicateDialog.test.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ const createMockComponentLibraryContext = (
4747
searchComponentLibrary: vi.fn(),
4848
addToComponentLibrary: vi.fn(),
4949
removeFromComponentLibrary: vi.fn(),
50-
checkIfUserComponent: vi.fn().mockReturnValue(false),
5150
getComponentLibrary: vi.fn(),
5251
};
5352
};

src/components/shared/FavoriteComponentToggle.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -142,27 +142,29 @@ const FavoriteToggleButton = withSuspenseWrapper(
142142
);
143143

144144
const useComponentFlags = (component: ComponentReference) => {
145-
const { checkIfUserComponent, getComponentLibrary } = useComponentLibrary();
145+
const { getComponentLibrary } = useComponentLibrary();
146146
const componentLibrary = getComponentLibrary("standard_components");
147+
const userComponentsLibrary = getComponentLibrary("user_components");
147148

148-
const isUserComponent = useMemo(
149-
() => checkIfUserComponent(component),
150-
[component, checkIfUserComponent],
151-
);
152-
153-
const { data: isInLibrary } = useSuspenseQuery({
149+
const { data } = useSuspenseQuery({
154150
queryKey: ["component", "flags", component.digest],
155151
queryFn: async () => {
156-
if (!componentLibrary) return false;
152+
if (!componentLibrary)
153+
return { isInLibrary: false, isUserComponent: false };
157154

158-
if (isUserComponent) return true;
155+
const isUserComponent =
156+
await userComponentsLibrary.hasComponent(component);
159157

160-
return componentLibrary.hasComponent(component);
158+
return {
159+
isInLibrary:
160+
isUserComponent || (await componentLibrary.hasComponent(component)),
161+
isUserComponent,
162+
};
161163
},
162164
staleTime: 10 * MINUTES,
163165
});
164166

165-
return { isInLibrary, isUserComponent };
167+
return data;
166168
};
167169

168170
const ComponentFavoriteToggleInternal = ({

src/components/shared/ReactFlow/FlowSidebar/sections/GraphComponents.tsx

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,11 @@ function ComponentLibrarySection() {
127127
useComponentLibrary();
128128

129129
const favoriteComponentsLibrary = getComponentLibrary("favorite_components");
130+
const userComponentsLibrary = getComponentLibrary("user_components");
130131

131132
const { updateSearchFilter } = useForcedSearchContext();
132-
const {
133-
usedComponentsFolder,
134-
userComponentsFolder,
135-
isLoading,
136-
error,
137-
searchResult,
138-
} = useComponentLibrary();
133+
const { usedComponentsFolder, isLoading, error, searchResult } =
134+
useComponentLibrary();
139135

140136
const standardComponentsLibrary = getComponentLibrary("standard_components");
141137

@@ -163,10 +159,6 @@ function ComponentLibrarySection() {
163159
usedComponentsFolder?.components &&
164160
usedComponentsFolder.components.length > 0;
165161

166-
const hasUserComponents =
167-
userComponentsFolder?.components &&
168-
userComponentsFolder.components.length > 0;
169-
170162
return (
171163
<BlockStack gap="2">
172164
{remoteComponentLibrarySearchEnabled && <UpgradeAvailableAlertBox />}
@@ -186,13 +178,11 @@ function ComponentLibrarySection() {
186178
icon="Star"
187179
/>
188180

189-
{hasUserComponents && (
190-
<FolderItem
191-
key="my-components-folder"
192-
folder={userComponentsFolder}
193-
icon="Puzzle"
194-
/>
195-
)}
181+
<LibraryFolderItem
182+
key="my-components-library-folder"
183+
library={userComponentsLibrary}
184+
icon="Puzzle"
185+
/>
196186
<Separator />
197187
<FolderItem
198188
key="graph-inputs-outputs-folder"

src/providers/ComponentLibraryProvider/ComponentLibraryProvider.test.tsx

Lines changed: 3 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ import yaml from "js-yaml";
44
import { type ReactNode } from "react";
55
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
66

7-
import type {
8-
ComponentFolder,
9-
ComponentLibrary,
10-
} from "@/types/componentLibrary";
7+
import type { ComponentFolder } from "@/types/componentLibrary";
118
import type {
129
ComponentReference,
1310
ComponentSpec,
@@ -43,30 +40,20 @@ vi.mock("./componentLibrary");
4340
import * as componentLibraryUtils from "@/providers/ComponentLibraryProvider/componentLibrary";
4441
import * as componentStore from "@/utils/componentStore";
4542
import * as getComponentName from "@/utils/getComponentName";
46-
import * as localforage from "@/utils/localforage";
4743

4844
// Mock implementations
4945

50-
const mockFetchUserComponents = vi.mocked(
51-
componentLibraryUtils.fetchUserComponents,
52-
);
5346
const mockFetchUsedComponents = vi.mocked(
5447
componentLibraryUtils.fetchUsedComponents,
5548
);
56-
const mockPopulateComponentRefs = vi.mocked(
57-
componentLibraryUtils.populateComponentRefs,
58-
);
5949
const mockFlattenFolders = vi.mocked(componentLibraryUtils.flattenFolders);
6050
const mockFilterToUniqueByDigest = vi.mocked(
6151
componentLibraryUtils.filterToUniqueByDigest,
6252
);
63-
const mockImportComponent = vi.mocked(componentStore.importComponent);
6453
const mockDeleteComponentFileFromList = vi.mocked(
6554
componentStore.deleteComponentFileFromList,
6655
);
67-
const mockGetUserComponentByName = vi.mocked(
68-
localforage.getUserComponentByName,
69-
);
56+
7057
const mockGetComponentName = vi.mocked(getComponentName.getComponentName);
7158

7259
describe("ComponentLibraryProvider - Component Management", () => {
@@ -79,36 +66,6 @@ describe("ComponentLibraryProvider - Component Management", () => {
7966
},
8067
};
8168

82-
const mockComponentLibrary: ComponentLibrary = {
83-
folders: [
84-
{
85-
name: "Test Folder",
86-
components: [
87-
{
88-
name: "test-component",
89-
digest: "test-digest-1",
90-
url: "https://example.com/component1.yaml",
91-
spec: mockComponentSpec,
92-
},
93-
],
94-
folders: [],
95-
},
96-
],
97-
};
98-
99-
const mockUserComponentsFolder: ComponentFolder = {
100-
name: "User Components",
101-
components: [
102-
{
103-
name: "user-component",
104-
digest: "user-digest-1",
105-
spec: mockComponentSpec,
106-
text: "test yaml content",
107-
},
108-
],
109-
folders: [],
110-
};
111-
11269
const createWrapper = ({ children }: { children: ReactNode }) => {
11370
const queryClient = new QueryClient({
11471
defaultOptions: {
@@ -131,13 +88,12 @@ describe("ComponentLibraryProvider - Component Management", () => {
13188
componentDuplicateDialogProps.handleImportComponent = undefined;
13289

13390
// Setup default mock implementations
134-
mockFetchUserComponents.mockResolvedValue(mockUserComponentsFolder);
13591
mockFetchUsedComponents.mockReturnValue({
13692
name: "Used Components",
13793
components: [],
13894
folders: [],
13995
});
140-
mockPopulateComponentRefs.mockImplementation((lib) => Promise.resolve(lib));
96+
14197
mockFlattenFolders.mockImplementation((folder) => {
14298
if ("folders" in folder) {
14399
return folder.folders?.flatMap((f) => f.components || []) || [];
@@ -207,16 +163,11 @@ describe("ComponentLibraryProvider - Component Management", () => {
207163

208164
// Mock that there's an existing component with the same name
209165
mockFlattenFolders.mockReturnValue([existingComponent]);
210-
mockGetUserComponentByName.mockResolvedValue(mockUserComponent);
211166

212167
const { result } = renderHook(() => useComponentLibrary(), {
213168
wrapper: createWrapper,
214169
});
215170

216-
await waitFor(() => {
217-
expect(result.current.isLoading).toBe(false);
218-
});
219-
220171
await act(async () => {
221172
void result.current.addToComponentLibrary(newComponent);
222173
});
@@ -481,51 +432,4 @@ describe("ComponentLibraryProvider - Component Management", () => {
481432
consoleSpy.mockRestore();
482433
});
483434
});
484-
485-
describe("Component Checks", () => {
486-
it("should correctly identify user components", async () => {
487-
const userComponent: ComponentReference = {
488-
name: "user-component",
489-
digest: "user-digest-1",
490-
spec: mockComponentSpec,
491-
};
492-
493-
mockFlattenFolders.mockReturnValue([userComponent]);
494-
mockFilterToUniqueByDigest.mockReturnValue([userComponent]);
495-
496-
const { result } = renderHook(() => useComponentLibrary(), {
497-
wrapper: createWrapper,
498-
});
499-
500-
await waitFor(() => {
501-
expect(result.current.isLoading).toBe(false);
502-
});
503-
504-
const isUserComponent =
505-
result.current.checkIfUserComponent(userComponent);
506-
expect(isUserComponent).toBe(true);
507-
});
508-
509-
it("should correctly identify non-user components", async () => {
510-
const standardComponent: ComponentReference = {
511-
name: "standard-component",
512-
digest: "standard-digest",
513-
spec: mockComponentSpec,
514-
};
515-
516-
mockFlattenFolders.mockReturnValue([]); // No user components
517-
518-
const { result } = renderHook(() => useComponentLibrary(), {
519-
wrapper: createWrapper,
520-
});
521-
522-
await waitFor(() => {
523-
expect(result.current.isLoading).toBe(false);
524-
});
525-
526-
const isUserComponent =
527-
result.current.checkIfUserComponent(standardComponent);
528-
expect(isUserComponent).toBe(false);
529-
});
530-
});
531435
});

0 commit comments

Comments
 (0)