@databiosphere/findable-ui 49.1.0 → 49.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +21 -0
- package/lib/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.d.ts +2 -3
- package/lib/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.js +3 -4
- package/lib/views/ResearchView/assistant/assistant.js +3 -5
- package/lib/views/ResearchView/assistant/components/Form/form.d.ts +1 -2
- package/lib/views/ResearchView/assistant/components/Form/form.js +5 -18
- package/lib/views/ResearchView/assistant/components/Form/types.d.ts +1 -2
- package/lib/views/ResearchView/assistant/components/Form/utils.d.ts +1 -1
- package/lib/views/ResearchView/assistant/components/Messages/hooks/UseScroll/hook.d.ts +2 -1
- package/lib/views/ResearchView/assistant/components/Messages/hooks/UseScroll/hook.js +5 -2
- package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.d.ts +2 -3
- package/lib/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.js +3 -4
- package/lib/views/ResearchView/assistant/stories/assistant.stories.js +1 -1
- package/lib/views/ResearchView/state/provider.d.ts +4 -1
- package/lib/views/ResearchView/state/provider.js +5 -2
- package/lib/views/ResearchView/state/query/context.d.ts +5 -0
- package/lib/views/ResearchView/state/query/context.js +7 -0
- package/lib/views/ResearchView/state/query/hooks/UseQuery/hook.d.ts +6 -0
- package/lib/views/ResearchView/state/query/hooks/UseQuery/hook.js +9 -0
- package/lib/views/ResearchView/state/query/hooks/UseSubmit/hook.d.ts +7 -0
- package/lib/views/ResearchView/state/query/hooks/UseSubmit/hook.js +46 -0
- package/lib/views/ResearchView/state/query/provider.d.ts +13 -0
- package/lib/views/ResearchView/state/query/provider.js +15 -0
- package/lib/views/ResearchView/{query → state/query}/types.d.ts +5 -12
- package/package.json +1 -1
- package/src/views/ExploreView/entityList/filters/components/ToggleButtonGroup/toggleButtonGroup.tsx +10 -6
- package/src/views/ResearchView/assistant/assistant.tsx +3 -5
- package/src/views/ResearchView/assistant/components/Form/form.tsx +4 -19
- package/src/views/ResearchView/assistant/components/Form/types.ts +0 -2
- package/src/views/ResearchView/assistant/components/Form/utils.ts +1 -1
- package/src/views/ResearchView/assistant/components/Messages/hooks/UseScroll/hook.ts +5 -2
- package/src/views/ResearchView/assistant/components/ToggleButtonGroup/toggleButtonGroup.tsx +10 -6
- package/src/views/ResearchView/assistant/stories/assistant.stories.tsx +1 -1
- package/src/views/ResearchView/state/provider.tsx +8 -1
- package/src/views/ResearchView/state/query/context.ts +9 -0
- package/src/views/ResearchView/state/query/hooks/UseQuery/hook.ts +11 -0
- package/src/views/ResearchView/state/query/hooks/UseSubmit/hook.ts +66 -0
- package/src/views/ResearchView/state/query/provider.tsx +27 -0
- package/src/views/ResearchView/{query → state/query}/types.ts +9 -15
- package/tests/research.queryProvider.test.ts +321 -0
- package/lib/views/ResearchView/adapter/useAdapter.d.ts +0 -6
- package/lib/views/ResearchView/adapter/useAdapter.js +0 -15
- package/lib/views/ResearchView/query/useQuery.d.ts +0 -7
- package/lib/views/ResearchView/query/useQuery.js +0 -44
- package/src/views/ResearchView/adapter/useAdapter.ts +0 -19
- package/src/views/ResearchView/query/useQuery.ts +0 -60
- package/tests/research.useQuery.test.ts +0 -165
- /package/lib/views/ResearchView/{query → state/query}/types.js +0 -0
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { FormEvent, useCallback, useEffect, useRef } from "react";
|
|
2
|
-
import { OnSubmitOptions, OnSubmitPayload, UseQuery } from "./types";
|
|
3
|
-
import { fetchResponse } from "./fetch";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Custom hook for managing the actions of a chat query form.
|
|
7
|
-
* @param url - The URL to send the query to.
|
|
8
|
-
* @returns An object containing the actions of the query.
|
|
9
|
-
*/
|
|
10
|
-
export const useQuery = (url: string): UseQuery => {
|
|
11
|
-
const abortRef = useRef<AbortController>(null);
|
|
12
|
-
|
|
13
|
-
const onSubmit = useCallback(
|
|
14
|
-
async (
|
|
15
|
-
e: FormEvent<HTMLFormElement>,
|
|
16
|
-
payload: OnSubmitPayload,
|
|
17
|
-
options?: OnSubmitOptions,
|
|
18
|
-
) => {
|
|
19
|
-
e.preventDefault();
|
|
20
|
-
|
|
21
|
-
if (options?.status?.loading) return;
|
|
22
|
-
|
|
23
|
-
const form = e.currentTarget;
|
|
24
|
-
const { query } = payload;
|
|
25
|
-
|
|
26
|
-
if (!query) return;
|
|
27
|
-
|
|
28
|
-
// Call onMutate callback
|
|
29
|
-
options?.onMutate?.(form, query);
|
|
30
|
-
|
|
31
|
-
// Abort any in-flight request
|
|
32
|
-
abortRef.current?.abort();
|
|
33
|
-
const controller = new AbortController();
|
|
34
|
-
abortRef.current = controller;
|
|
35
|
-
|
|
36
|
-
await fetchResponse(url, query, {
|
|
37
|
-
controller,
|
|
38
|
-
onError: (error) => {
|
|
39
|
-
options?.onError?.(error);
|
|
40
|
-
},
|
|
41
|
-
onSettled: () => {
|
|
42
|
-
options?.onSettled?.(form);
|
|
43
|
-
},
|
|
44
|
-
onSuccess: (data) => {
|
|
45
|
-
options?.onSuccess?.(data);
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
},
|
|
49
|
-
[url],
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
// Abort any in-flight request on unmount.
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
return (): void => {
|
|
55
|
-
abortRef.current?.abort();
|
|
56
|
-
};
|
|
57
|
-
}, []);
|
|
58
|
-
|
|
59
|
-
return { actions: { onSubmit } };
|
|
60
|
-
};
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { jest } from "@jest/globals";
|
|
2
|
-
import { act, renderHook } from "@testing-library/react";
|
|
3
|
-
import { FormEvent } from "react";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Fetch callbacks passed to fetchResponse.
|
|
7
|
-
*/
|
|
8
|
-
interface FetchCallbacks {
|
|
9
|
-
controller: AbortController;
|
|
10
|
-
onError: (error: Error) => void;
|
|
11
|
-
onSettled: () => void;
|
|
12
|
-
onSuccess: (data: unknown) => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Mock fetchResponse
|
|
16
|
-
const mockFetchResponse = jest.fn();
|
|
17
|
-
|
|
18
|
-
jest.unstable_mockModule("../src/views/ResearchView/query/fetch", () => ({
|
|
19
|
-
fetchResponse: mockFetchResponse,
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
const { useQuery } = await import("../src/views/ResearchView/query/useQuery");
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Creates a mock form event for testing.
|
|
26
|
-
* @returns Mock FormEvent.
|
|
27
|
-
*/
|
|
28
|
-
function createMockFormEvent(): FormEvent<HTMLFormElement> {
|
|
29
|
-
const mockForm = document.createElement("form");
|
|
30
|
-
|
|
31
|
-
// Mock reset
|
|
32
|
-
mockForm.reset = jest.fn();
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
currentTarget: mockForm,
|
|
36
|
-
preventDefault: jest.fn(),
|
|
37
|
-
} as unknown as FormEvent<HTMLFormElement>;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
describe("useQuery", () => {
|
|
41
|
-
beforeEach(() => {
|
|
42
|
-
mockFetchResponse.mockReset();
|
|
43
|
-
mockFetchResponse.mockImplementation(
|
|
44
|
-
async (_url: unknown, _query: unknown, callbacks: unknown) => {
|
|
45
|
-
(callbacks as FetchCallbacks).onSettled();
|
|
46
|
-
},
|
|
47
|
-
);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
describe("initial state", () => {
|
|
51
|
-
it("should return onSubmit function", () => {
|
|
52
|
-
const { result } = renderHook(() => useQuery("https://api.example.com"));
|
|
53
|
-
|
|
54
|
-
expect(typeof result.current.actions.onSubmit).toBe("function");
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
describe("submit guards", () => {
|
|
59
|
-
it("should not submit if query is empty", async () => {
|
|
60
|
-
const { result } = renderHook(() => useQuery("https://api.example.com"));
|
|
61
|
-
const event = createMockFormEvent();
|
|
62
|
-
|
|
63
|
-
await act(async () => {
|
|
64
|
-
await result.current.actions.onSubmit(event, { query: "" });
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
expect(mockFetchResponse).not.toHaveBeenCalled();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("should submit if query is provided", async () => {
|
|
71
|
-
const { result } = renderHook(() => useQuery("https://api.example.com"));
|
|
72
|
-
const event = createMockFormEvent();
|
|
73
|
-
|
|
74
|
-
await act(async () => {
|
|
75
|
-
await result.current.actions.onSubmit(event, { query: "valid query" });
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
expect(mockFetchResponse).toHaveBeenCalled();
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
describe("submit behavior", () => {
|
|
83
|
-
it("should call preventDefault on form event", async () => {
|
|
84
|
-
const { result } = renderHook(() => useQuery("https://api.example.com"));
|
|
85
|
-
const event = createMockFormEvent();
|
|
86
|
-
|
|
87
|
-
await act(async () => {
|
|
88
|
-
await result.current.actions.onSubmit(event, {
|
|
89
|
-
query: "diabetes studies",
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
expect(event.preventDefault).toHaveBeenCalled();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it("should call fetchResponse with correct arguments", async () => {
|
|
97
|
-
const { result } = renderHook(() => useQuery("https://api.example.com"));
|
|
98
|
-
const event = createMockFormEvent();
|
|
99
|
-
|
|
100
|
-
await act(async () => {
|
|
101
|
-
await result.current.actions.onSubmit(event, {
|
|
102
|
-
query: "diabetes studies",
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
expect(mockFetchResponse).toHaveBeenCalledWith(
|
|
107
|
-
"https://api.example.com",
|
|
108
|
-
"diabetes studies",
|
|
109
|
-
expect.objectContaining({
|
|
110
|
-
controller: expect.any(AbortController),
|
|
111
|
-
onError: expect.any(Function),
|
|
112
|
-
onSettled: expect.any(Function),
|
|
113
|
-
onSuccess: expect.any(Function),
|
|
114
|
-
}),
|
|
115
|
-
);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("should pass url to fetchResponse", async () => {
|
|
119
|
-
const testUrl = "https://custom-api.example.com/search";
|
|
120
|
-
const { result } = renderHook(() => useQuery(testUrl));
|
|
121
|
-
const event = createMockFormEvent();
|
|
122
|
-
|
|
123
|
-
await act(async () => {
|
|
124
|
-
await result.current.actions.onSubmit(event, {
|
|
125
|
-
query: "cancer studies",
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
expect(mockFetchResponse).toHaveBeenCalledWith(
|
|
130
|
-
testUrl,
|
|
131
|
-
expect.any(String),
|
|
132
|
-
expect.any(Object),
|
|
133
|
-
);
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
describe("abort handling", () => {
|
|
138
|
-
it("should create new AbortController for each submit", async () => {
|
|
139
|
-
const controllers: AbortController[] = [];
|
|
140
|
-
mockFetchResponse.mockImplementation(
|
|
141
|
-
async (_url: unknown, _query: unknown, callbacks: unknown) => {
|
|
142
|
-
controllers.push((callbacks as FetchCallbacks).controller);
|
|
143
|
-
(callbacks as FetchCallbacks).onSettled();
|
|
144
|
-
},
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
const { result } = renderHook(() => useQuery("https://api.example.com"));
|
|
148
|
-
|
|
149
|
-
await act(async () => {
|
|
150
|
-
await result.current.actions.onSubmit(createMockFormEvent(), {
|
|
151
|
-
query: "query 1",
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
await act(async () => {
|
|
156
|
-
await result.current.actions.onSubmit(createMockFormEvent(), {
|
|
157
|
-
query: "query 2",
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
expect(controllers).toHaveLength(2);
|
|
162
|
-
expect(controllers[0]).not.toBe(controllers[1]);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
});
|
|
File without changes
|