mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-19 23:31:21 +02:00
query client cache and better body types
This commit is contained in:
111
package-lock.json
generated
111
package-lock.json
generated
@@ -20,8 +20,10 @@
|
|||||||
"@lezer/lr": "^1.3.3",
|
"@lezer/lr": "^1.3.3",
|
||||||
"@radix-ui/react-icons": "^1.2.0",
|
"@radix-ui/react-icons": "^1.2.0",
|
||||||
"@tailwindcss/container-queries": "^0.1.0",
|
"@tailwindcss/container-queries": "^0.1.0",
|
||||||
"@tanstack/react-query": "^4.24.10",
|
"@tanstack/query-sync-storage-persister": "^4.27.1",
|
||||||
"@tanstack/react-query-devtools": "^4.26.1",
|
"@tanstack/react-query": "^4.28.0",
|
||||||
|
"@tanstack/react-query-devtools": "^4.28.0",
|
||||||
|
"@tanstack/react-query-persist-client": "^4.28.0",
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@tauri-apps/api": "^1.2.0",
|
||||||
"@vitejs/plugin-react": "^3.1.0",
|
"@vitejs/plugin-react": "^3.1.0",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
@@ -1485,20 +1487,44 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tanstack/query-core": {
|
"node_modules/@tanstack/query-core": {
|
||||||
"version": "4.26.1",
|
"version": "4.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.27.0.tgz",
|
||||||
"integrity": "sha512-Zrx2pVQUP4ndnsu6+K/m8zerXSVY8QM+YSbxA1/jbBY21GeCd5oKfYl92oXPK0hPEUtoNuunIdiq0ZMqLos+Zg==",
|
"integrity": "sha512-sm+QncWaPmM73IPwFlmWSKPqjdTXZeFf/7aEmWh00z7yl2FjqophPt0dE1EHW9P1giMC5rMviv7OUbSDmWzXXA==",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tanstack/query-persist-client-core": {
|
||||||
|
"version": "4.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-4.27.0.tgz",
|
||||||
|
"integrity": "sha512-A+dPA7zG0MJOMDeBc/2WcKXW4wV2JMkeBVydobPW9G02M4q0yAj7vI+7SmM2dFuXyIvxXp4KulCywN6abRKDSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/query-core": "4.27.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tanstack/query-sync-storage-persister": {
|
||||||
|
"version": "4.27.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/query-sync-storage-persister/-/query-sync-storage-persister-4.27.1.tgz",
|
||||||
|
"integrity": "sha512-vClLXtyQZwfV8QTyxqfkEzZSuwIKnrxORAUyxvCDna1M9xao0HtKYsChPVaJoSZ42PNGGvKCiKdg4kfyLeWj+A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/query-persist-client-core": "4.27.0"
|
||||||
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/tannerlinsley"
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tanstack/react-query": {
|
"node_modules/@tanstack/react-query": {
|
||||||
"version": "4.26.1",
|
"version": "4.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.28.0.tgz",
|
||||||
"integrity": "sha512-i3dnz4TOARGIXrXQ5P7S25Zfi4noii/bxhcwPurh2nrf5EUCcAt/95TB2HSmMweUBx206yIMWUMEQ7ptd6zwDg==",
|
"integrity": "sha512-8cGBV5300RHlvYdS4ea+G1JcZIt5CIuprXYFnsWggkmGoC0b5JaqG0fIX3qwDL9PTNkKvG76NGThIWbpXivMrQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/query-core": "4.26.1",
|
"@tanstack/query-core": "4.27.0",
|
||||||
"use-sync-external-store": "^1.2.0"
|
"use-sync-external-store": "^1.2.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
@@ -1520,9 +1546,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tanstack/react-query-devtools": {
|
"node_modules/@tanstack/react-query-devtools": {
|
||||||
"version": "4.26.1",
|
"version": "4.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.28.0.tgz",
|
||||||
"integrity": "sha512-ts2mA+fyFYFRi3Cee4xBk8Fx6waSFOM+yCkFqwJfGQRGjjTIMYMZPJv4wkv7vy12IVi1SYhL8au22LRKlXS1Zg==",
|
"integrity": "sha512-1SnoMw1CWn8FdPEIHvlAzmMBX3heXJo11fyBtt+FzYAHj5yFC8P67Kpgi0HpLkY7SLnd6QK/7qFkpeH4AQbgZg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/match-sorter-utils": "^8.7.0",
|
"@tanstack/match-sorter-utils": "^8.7.0",
|
||||||
"superjson": "^1.10.0",
|
"superjson": "^1.10.0",
|
||||||
@@ -1533,11 +1559,26 @@
|
|||||||
"url": "https://github.com/sponsors/tannerlinsley"
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@tanstack/react-query": "4.26.1",
|
"@tanstack/react-query": "4.28.0",
|
||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tanstack/react-query-persist-client": {
|
||||||
|
"version": "4.28.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-4.28.0.tgz",
|
||||||
|
"integrity": "sha512-xNpi3YdPOQIyYkKhByYDqTlyCeqICWFhV5PWkoVxYfzlRK6HYX4s+9Int407jEvhBz9cGC4OaL7rd6bynCFrYg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/query-persist-client-core": "4.27.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@tanstack/react-query": "4.28.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tauri-apps/api": {
|
"node_modules/@tauri-apps/api": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.2.0.tgz",
|
||||||
@@ -8257,29 +8298,53 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@tanstack/query-core": {
|
"@tanstack/query-core": {
|
||||||
"version": "4.26.1",
|
"version": "4.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.27.0.tgz",
|
||||||
"integrity": "sha512-Zrx2pVQUP4ndnsu6+K/m8zerXSVY8QM+YSbxA1/jbBY21GeCd5oKfYl92oXPK0hPEUtoNuunIdiq0ZMqLos+Zg=="
|
"integrity": "sha512-sm+QncWaPmM73IPwFlmWSKPqjdTXZeFf/7aEmWh00z7yl2FjqophPt0dE1EHW9P1giMC5rMviv7OUbSDmWzXXA=="
|
||||||
|
},
|
||||||
|
"@tanstack/query-persist-client-core": {
|
||||||
|
"version": "4.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-4.27.0.tgz",
|
||||||
|
"integrity": "sha512-A+dPA7zG0MJOMDeBc/2WcKXW4wV2JMkeBVydobPW9G02M4q0yAj7vI+7SmM2dFuXyIvxXp4KulCywN6abRKDSQ==",
|
||||||
|
"requires": {
|
||||||
|
"@tanstack/query-core": "4.27.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tanstack/query-sync-storage-persister": {
|
||||||
|
"version": "4.27.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/query-sync-storage-persister/-/query-sync-storage-persister-4.27.1.tgz",
|
||||||
|
"integrity": "sha512-vClLXtyQZwfV8QTyxqfkEzZSuwIKnrxORAUyxvCDna1M9xao0HtKYsChPVaJoSZ42PNGGvKCiKdg4kfyLeWj+A==",
|
||||||
|
"requires": {
|
||||||
|
"@tanstack/query-persist-client-core": "4.27.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"@tanstack/react-query": {
|
"@tanstack/react-query": {
|
||||||
"version": "4.26.1",
|
"version": "4.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.28.0.tgz",
|
||||||
"integrity": "sha512-i3dnz4TOARGIXrXQ5P7S25Zfi4noii/bxhcwPurh2nrf5EUCcAt/95TB2HSmMweUBx206yIMWUMEQ7ptd6zwDg==",
|
"integrity": "sha512-8cGBV5300RHlvYdS4ea+G1JcZIt5CIuprXYFnsWggkmGoC0b5JaqG0fIX3qwDL9PTNkKvG76NGThIWbpXivMrQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@tanstack/query-core": "4.26.1",
|
"@tanstack/query-core": "4.27.0",
|
||||||
"use-sync-external-store": "^1.2.0"
|
"use-sync-external-store": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@tanstack/react-query-devtools": {
|
"@tanstack/react-query-devtools": {
|
||||||
"version": "4.26.1",
|
"version": "4.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.28.0.tgz",
|
||||||
"integrity": "sha512-ts2mA+fyFYFRi3Cee4xBk8Fx6waSFOM+yCkFqwJfGQRGjjTIMYMZPJv4wkv7vy12IVi1SYhL8au22LRKlXS1Zg==",
|
"integrity": "sha512-1SnoMw1CWn8FdPEIHvlAzmMBX3heXJo11fyBtt+FzYAHj5yFC8P67Kpgi0HpLkY7SLnd6QK/7qFkpeH4AQbgZg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@tanstack/match-sorter-utils": "^8.7.0",
|
"@tanstack/match-sorter-utils": "^8.7.0",
|
||||||
"superjson": "^1.10.0",
|
"superjson": "^1.10.0",
|
||||||
"use-sync-external-store": "^1.2.0"
|
"use-sync-external-store": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@tanstack/react-query-persist-client": {
|
||||||
|
"version": "4.28.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-4.28.0.tgz",
|
||||||
|
"integrity": "sha512-xNpi3YdPOQIyYkKhByYDqTlyCeqICWFhV5PWkoVxYfzlRK6HYX4s+9Int407jEvhBz9cGC4OaL7rd6bynCFrYg==",
|
||||||
|
"requires": {
|
||||||
|
"@tanstack/query-persist-client-core": "4.27.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@tauri-apps/api": {
|
"@tauri-apps/api": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-1.2.0.tgz",
|
||||||
|
|||||||
@@ -27,8 +27,10 @@
|
|||||||
"@lezer/lr": "^1.3.3",
|
"@lezer/lr": "^1.3.3",
|
||||||
"@radix-ui/react-icons": "^1.2.0",
|
"@radix-ui/react-icons": "^1.2.0",
|
||||||
"@tailwindcss/container-queries": "^0.1.0",
|
"@tailwindcss/container-queries": "^0.1.0",
|
||||||
"@tanstack/react-query": "^4.24.10",
|
"@tanstack/query-sync-storage-persister": "^4.27.1",
|
||||||
"@tanstack/react-query-devtools": "^4.26.1",
|
"@tanstack/react-query": "^4.28.0",
|
||||||
|
"@tanstack/react-query-devtools": "^4.28.0",
|
||||||
|
"@tanstack/react-query-persist-client": "^4.28.0",
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@tauri-apps/api": "^1.2.0",
|
||||||
"@vitejs/plugin-react": "^3.1.0",
|
"@vitejs/plugin-react": "^3.1.0",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister';
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||||
|
import { persistQueryClient } from '@tanstack/react-query-persist-client';
|
||||||
import { invoke } from '@tauri-apps/api';
|
import { invoke } from '@tauri-apps/api';
|
||||||
import { listen } from '@tauri-apps/api/event';
|
import { listen } from '@tauri-apps/api/event';
|
||||||
import { MotionConfig } from 'framer-motion';
|
import { MotionConfig } from 'framer-motion';
|
||||||
@@ -18,7 +20,25 @@ import type { HttpRequest, HttpResponse, KeyValue, Workspace } from '../lib/mode
|
|||||||
import { convertDates } from '../lib/models';
|
import { convertDates } from '../lib/models';
|
||||||
import { AppRouter } from './AppRouter';
|
import { AppRouter } from './AppRouter';
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient({
|
||||||
|
defaultOptions: {
|
||||||
|
queries: {
|
||||||
|
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
|
||||||
|
networkMode: 'offlineFirst',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const localStoragePersister = createSyncStoragePersister({
|
||||||
|
storage: window.localStorage,
|
||||||
|
throttleTime: 1000,
|
||||||
|
});
|
||||||
|
|
||||||
|
persistQueryClient({
|
||||||
|
queryClient,
|
||||||
|
persister: localStoragePersister,
|
||||||
|
maxAge: 1000 * 60 * 60 * 24, // 24 hours
|
||||||
|
});
|
||||||
|
|
||||||
await listen('updated_key_value', ({ payload: keyValue }: { payload: KeyValue }) => {
|
await listen('updated_key_value', ({ payload: keyValue }: { payload: KeyValue }) => {
|
||||||
queryClient.setQueryData(keyValueQueryKey(keyValue), extractKeyValue(keyValue));
|
queryClient.setQueryData(keyValueQueryKey(keyValue), extractKeyValue(keyValue));
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { useActiveRequest } from '../hooks/useActiveRequest';
|
|||||||
import { useKeyValue } from '../hooks/useKeyValue';
|
import { useKeyValue } from '../hooks/useKeyValue';
|
||||||
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
||||||
import { tryFormatJson } from '../lib/formatters';
|
import { tryFormatJson } from '../lib/formatters';
|
||||||
import type { HttpHeader } from '../lib/models';
|
import type { HttpHeader, HttpRequest } from '../lib/models';
|
||||||
|
import { HttpRequestBodyType } from '../lib/models';
|
||||||
import { Editor } from './core/Editor';
|
import { Editor } from './core/Editor';
|
||||||
import type { TabItem } from './core/Tabs/Tabs';
|
import type { TabItem } from './core/Tabs/Tabs';
|
||||||
import { TabContent, Tabs } from './core/Tabs/Tabs';
|
import { TabContent, Tabs } from './core/Tabs/Tabs';
|
||||||
@@ -27,19 +28,25 @@ export function RequestPane({ fullHeight, className }: Props) {
|
|||||||
defaultValue: 'body',
|
defaultValue: 'body',
|
||||||
});
|
});
|
||||||
|
|
||||||
const tabs: TabItem<string | null>[] = useMemo(
|
const tabs: TabItem<HttpRequest['bodyType']>[] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
value: 'body',
|
value: 'body',
|
||||||
label: activeRequest?.bodyType ?? 'No Body',
|
label: activeRequest?.bodyType ?? 'No Body',
|
||||||
options: {
|
options: {
|
||||||
onChange: (bodyType: string | null) => updateRequest.mutate({ bodyType }),
|
onChange: (bodyType: HttpRequest['bodyType']) => {
|
||||||
|
const patch: Partial<HttpRequest> = { bodyType };
|
||||||
|
if (bodyType == HttpRequestBodyType.GraphQL) {
|
||||||
|
patch.method = 'POST';
|
||||||
|
}
|
||||||
|
updateRequest.mutate(patch);
|
||||||
|
},
|
||||||
value: activeRequest?.bodyType ?? null,
|
value: activeRequest?.bodyType ?? null,
|
||||||
items: [
|
items: [
|
||||||
{ label: 'No Body', value: null },
|
{ label: 'No Body', value: null },
|
||||||
{ label: 'JSON', value: 'json' },
|
{ label: 'JSON', value: HttpRequestBodyType.JSON },
|
||||||
{ label: 'XML', value: 'xml' },
|
{ label: 'XML', value: HttpRequestBodyType.XML },
|
||||||
{ label: 'GraphQL', value: 'graphql' },
|
{ label: 'GraphQL', value: HttpRequestBodyType.GraphQL },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -85,7 +92,7 @@ export function RequestPane({ fullHeight, className }: Props) {
|
|||||||
<ParametersEditor key={activeRequestId} parameters={[]} onChange={() => null} />
|
<ParametersEditor key={activeRequestId} parameters={[]} onChange={() => null} />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value="body" className="pl-3 mt-1">
|
<TabContent value="body" className="pl-3 mt-1">
|
||||||
{activeRequest.bodyType === 'json' ? (
|
{activeRequest.bodyType === HttpRequestBodyType.JSON ? (
|
||||||
<Editor
|
<Editor
|
||||||
key={activeRequest.id}
|
key={activeRequest.id}
|
||||||
useTemplating
|
useTemplating
|
||||||
@@ -96,7 +103,7 @@ export function RequestPane({ fullHeight, className }: Props) {
|
|||||||
onChange={handleBodyChange}
|
onChange={handleBodyChange}
|
||||||
format={(v) => tryFormatJson(v)}
|
format={(v) => tryFormatJson(v)}
|
||||||
/>
|
/>
|
||||||
) : activeRequest.bodyType === 'xml' ? (
|
) : activeRequest.bodyType === HttpRequestBodyType.XML ? (
|
||||||
<Editor
|
<Editor
|
||||||
key={activeRequest.id}
|
key={activeRequest.id}
|
||||||
useTemplating
|
useTemplating
|
||||||
@@ -106,7 +113,7 @@ export function RequestPane({ fullHeight, className }: Props) {
|
|||||||
contentType="text/xml"
|
contentType="text/xml"
|
||||||
onChange={handleBodyChange}
|
onChange={handleBodyChange}
|
||||||
/>
|
/>
|
||||||
) : activeRequest.bodyType === 'graphql' ? (
|
) : activeRequest.bodyType === HttpRequestBodyType.GraphQL ? (
|
||||||
<GraphQLEditor
|
<GraphQLEditor
|
||||||
key={activeRequest.id}
|
key={activeRequest.id}
|
||||||
className="!bg-gray-50"
|
className="!bg-gray-50"
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default function Workspace() {
|
|||||||
// TODO: Use container query subscription instead of minitoring everything
|
// TODO: Use container query subscription instead of minitoring everything
|
||||||
}, [mainContentRef.current, windowSize, sidebarWidth.value]);
|
}, [mainContentRef.current, windowSize, sidebarWidth.value]);
|
||||||
|
|
||||||
const isSideBySide = mainContentWidth > 700;
|
const isSideBySide = mainContentWidth > 900;
|
||||||
|
|
||||||
if (activeWorkspace == null) {
|
if (activeWorkspace == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
|
||||||
import { useActiveWorkspaceId } from '../hooks/useActiveWorkspaceId';
|
import { useActiveWorkspaceId } from '../hooks/useActiveWorkspaceId';
|
||||||
import { useCreateWorkspace } from '../hooks/useCreateWorkspace';
|
import { useCreateWorkspace } from '../hooks/useCreateWorkspace';
|
||||||
@@ -16,12 +17,12 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const WorkspaceDropdown = memo(function WorkspaceDropdown({ className }: Props) {
|
export const WorkspaceDropdown = memo(function WorkspaceDropdown({ className }: Props) {
|
||||||
const routes = useRoutes();
|
|
||||||
const workspaces = useWorkspaces();
|
const workspaces = useWorkspaces();
|
||||||
const activeWorkspace = useActiveWorkspace();
|
const activeWorkspace = useActiveWorkspace();
|
||||||
const activeWorkspaceId = useActiveWorkspaceId();
|
const activeWorkspaceId = activeWorkspace?.id ?? null;
|
||||||
const createWorkspace = useCreateWorkspace({ navigateAfter: true });
|
const createWorkspace = useCreateWorkspace({ navigateAfter: true });
|
||||||
const deleteWorkspace = useDeleteWorkspace(activeWorkspaceId);
|
const deleteWorkspace = useDeleteWorkspace(activeWorkspaceId);
|
||||||
|
const routes = useRoutes();
|
||||||
|
|
||||||
const items: DropdownItem[] = useMemo(() => {
|
const items: DropdownItem[] = useMemo(() => {
|
||||||
const workspaceItems = workspaces.map((w) => ({
|
const workspaceItems = workspaces.map((w) => ({
|
||||||
@@ -52,7 +53,7 @@ export const WorkspaceDropdown = memo(function WorkspaceDropdown({ className }:
|
|||||||
return (
|
return (
|
||||||
<Dropdown items={items}>
|
<Dropdown items={items}>
|
||||||
<Button size="sm" className={classnames(className, '!px-2 truncate')} forDropdown>
|
<Button size="sm" className={classnames(className, '!px-2 truncate')} forDropdown>
|
||||||
{activeWorkspace?.name ?? 'Unknown'}
|
{activeWorkspace?.name}
|
||||||
</Button>
|
</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -271,6 +271,7 @@ const FormRow = memo(function FormRow({
|
|||||||
onChange={handleChangeEnabled}
|
onChange={handleChangeEnabled}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
onDragStart={(e) => e.preventDefault()}
|
||||||
className={classnames(
|
className={classnames(
|
||||||
'grid items-center',
|
'grid items-center',
|
||||||
'@xs:gap-2 @xs:!grid-rows-1 @xs:!grid-cols-[minmax(0,1fr)_minmax(0,1fr)]',
|
'@xs:gap-2 @xs:!grid-rows-1 @xs:!grid-cols-[minmax(0,1fr)_minmax(0,1fr)]',
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
.tab-content {
|
|
||||||
&[data-state="inactive"] {
|
|
||||||
@apply hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,9 +7,7 @@ import type { RadioDropdownProps } from '../RadioDropdown';
|
|||||||
import { RadioDropdown } from '../RadioDropdown';
|
import { RadioDropdown } from '../RadioDropdown';
|
||||||
import { HStack } from '../Stacks';
|
import { HStack } from '../Stacks';
|
||||||
|
|
||||||
import './Tabs.css';
|
export type TabItem<T = string> = {
|
||||||
|
|
||||||
export type TabItem<T> = {
|
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
options?: Omit<RadioDropdownProps<T>, 'children'>;
|
options?: Omit<RadioDropdownProps<T>, 'children'>;
|
||||||
@@ -37,14 +35,18 @@ export function Tabs<T>({
|
|||||||
const ref = useRef<HTMLDivElement | null>(null);
|
const ref = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
const handleTabChange = (value: string) => {
|
const handleTabChange = (value: string) => {
|
||||||
const tabs = ref.current?.querySelectorAll(`[data-tab]`);
|
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
|
||||||
for (const tab of tabs ?? []) {
|
for (const tab of tabs ?? []) {
|
||||||
const v = tab.getAttribute('data-tab');
|
const v = tab.getAttribute('data-tab');
|
||||||
if (v === value) {
|
if (v === value) {
|
||||||
tab.setAttribute('tabindex', '-1');
|
tab.setAttribute('tabindex', '-1');
|
||||||
tab.setAttribute('data-state', 'active');
|
tab.setAttribute('data-state', 'active');
|
||||||
|
tab.setAttribute('aria-hidden', 'false');
|
||||||
|
tab.style.display = 'block';
|
||||||
} else {
|
} else {
|
||||||
tab.setAttribute('data-state', 'inactive');
|
tab.setAttribute('data-state', 'inactive');
|
||||||
|
tab.setAttribute('aria-hidden', 'true');
|
||||||
|
tab.style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onChangeValue(value);
|
onChangeValue(value);
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
import type { Workspace } from '../lib/models';
|
import type { Workspace } from '../lib/models';
|
||||||
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
|
||||||
import { useWorkspaces } from './useWorkspaces';
|
import { useWorkspaces } from './useWorkspaces';
|
||||||
|
|
||||||
export function useActiveWorkspace(): Workspace | null {
|
export function useActiveWorkspace(): Workspace | null {
|
||||||
const workspaces = useWorkspaces();
|
|
||||||
const workspaceId = useActiveWorkspaceId();
|
const workspaceId = useActiveWorkspaceId();
|
||||||
const [activeWorkspace, setActiveWorkspace] = useState<Workspace | null>(null);
|
const workspaces = useWorkspaces();
|
||||||
|
return useMemo(
|
||||||
useEffect(() => {
|
() => workspaces.find((w) => w.id === workspaceId) ?? null,
|
||||||
setActiveWorkspace(workspaces.find((w) => w.id === workspaceId) ?? null);
|
[workspaces, workspaceId],
|
||||||
}, [workspaces, workspaceId]);
|
);
|
||||||
|
|
||||||
return activeWorkspace;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ export interface HttpHeader {
|
|||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum HttpRequestBodyType {
|
||||||
|
GraphQL = 'graphql',
|
||||||
|
JSON = 'application/json',
|
||||||
|
XML = 'text/xml',
|
||||||
|
}
|
||||||
|
|
||||||
export interface HttpRequest extends BaseModel {
|
export interface HttpRequest extends BaseModel {
|
||||||
readonly workspaceId: string;
|
readonly workspaceId: string;
|
||||||
readonly model: 'http_request';
|
readonly model: 'http_request';
|
||||||
@@ -23,7 +29,7 @@ export interface HttpRequest extends BaseModel {
|
|||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
body: string | null;
|
body: string | null;
|
||||||
bodyType: string | null;
|
bodyType: HttpRequestBodyType | null;
|
||||||
method: string;
|
method: string;
|
||||||
headers: HttpHeader[];
|
headers: HttpHeader[];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user