refactor: standardize request methods (#3075)
* refactor: use table pagination in all list pages
* feat: gen hooks from factory func
* fix: logic
* fix: detail query options
* fix:
* chore
* fix: credentials params
* fix(useSearchParams): `setParams` type
diff --git a/src/apis/consumer_groups.ts b/src/apis/consumer_groups.ts
index 189e46a..f7f7386 100644
--- a/src/apis/consumer_groups.ts
+++ b/src/apis/consumer_groups.ts
@@ -14,41 +14,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { queryOptions } from '@tanstack/react-query';
+import type { AxiosInstance } from 'axios';
import { API_CONSUMER_GROUPS } from '@/config/constant';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import type { PageSearchType } from '@/types/schema/pageSearch';
-export const getConsumerGroupListQueryOptions = (props: PageSearchType) => {
- const { page, pageSize } = props;
- return queryOptions({
- queryKey: ['consumer_groups', page, pageSize],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespConsumerGroupList']>(
- API_CONSUMER_GROUPS,
- {
- params: { page, page_size: pageSize },
- }
- )
- .then((v) => v.data),
- });
-};
+export const getConsumerGroupListReq = (
+ req: AxiosInstance,
+ params: PageSearchType
+) =>
+ req
+ .get<unknown, APISIXType['RespConsumerGroupList']>(API_CONSUMER_GROUPS, {
+ params,
+ })
+ .then((v) => v.data);
-export const getConsumerGroupQueryOptions = (id: string) =>
- queryOptions({
- queryKey: ['consumer_group', id],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespConsumerGroupDetail']>(
- `${API_CONSUMER_GROUPS}/${id}`
- )
- .then((v) => v.data),
- });
+export const getConsumerGroupReq = (req: AxiosInstance, id: string) =>
+ req
+ .get<unknown, APISIXType['RespConsumerGroupDetail']>(
+ `${API_CONSUMER_GROUPS}/${id}`
+ )
+ .then((v) => v.data);
-export const putConsumerGroupReq = (data: APISIXType['ConsumerGroupPut']) => {
+export const putConsumerGroupReq = (
+ req: AxiosInstance,
+ data: APISIXType['ConsumerGroupPut']
+) => {
const { id, ...rest } = data;
return req.put<
APISIXType['ConsumerGroupPut'],
diff --git a/src/apis/consumers.ts b/src/apis/consumers.ts
index f19aa18..c4779df 100644
--- a/src/apis/consumers.ts
+++ b/src/apis/consumers.ts
@@ -14,36 +14,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { queryOptions } from '@tanstack/react-query';
+import type { AxiosInstance } from 'axios';
import { API_CONSUMERS } from '@/config/constant';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import type { PageSearchType } from '@/types/schema/pageSearch';
-export const getConsumerListQueryOptions = (props: PageSearchType) => {
- const { page, pageSize } = props;
- return queryOptions({
- queryKey: ['consumers', page, pageSize],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespConsumerList']>(API_CONSUMERS, {
- params: { page, page_size: pageSize },
- })
- .then((v) => v.data),
- });
-};
+export const getConsumerListReq = (req: AxiosInstance, params: PageSearchType) =>
+ req
+ .get<unknown, APISIXType['RespConsumerList']>(API_CONSUMERS, {
+ params,
+ })
+ .then((v) => v.data);
-export const getConsumerQueryOptions = (username: string) =>
- queryOptions({
- queryKey: ['consumer', username],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespConsumerDetail']>(`${API_CONSUMERS}/${username}`)
- .then((v) => v.data),
- });
+export const getConsumerReq = (req: AxiosInstance, username: string) =>
+ req
+ .get<unknown, APISIXType['RespConsumerDetail']>(
+ `${API_CONSUMERS}/${username}`
+ )
+ .then((v) => v.data);
-export const putConsumerReq = (data: APISIXType['ConsumerPut']) => {
+export const putConsumerReq = (
+ req: AxiosInstance,
+ data: APISIXType['ConsumerPut']
+) => {
return req.put<APISIXType['ConsumerPut'], APISIXType['RespConsumerDetail']>(
API_CONSUMERS,
data
diff --git a/src/apis/credentials.ts b/src/apis/credentials.ts
index 9453717..5744598 100644
--- a/src/apis/credentials.ts
+++ b/src/apis/credentials.ts
@@ -14,55 +14,48 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { queryOptions } from '@tanstack/react-query';
+
+import type { AxiosInstance } from 'axios';
import { API_CREDENTIALS, SKIP_INTERCEPTOR_HEADER } from '@/config/constant';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import type { APISIXListResponse } from '@/types/schema/apisix/type';
-type WithUsername = Pick<APISIXType['Consumer'], 'username'>;
-export const getCredentialListQueryOptions = (props: WithUsername) => {
- const { username } = props;
- return queryOptions({
- queryKey: ['credentials', username],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespCredentialList']>(
- API_CREDENTIALS(username),
- {
- headers: {
- [SKIP_INTERCEPTOR_HEADER]: ['404'],
- },
- }
- )
- .then((v) => v.data)
- .catch((e) => {
- // 404 means credentials is empty
- if (e.response.status === 404) {
- const res: APISIXListResponse<APISIXType['Credential']> = {
- total: 0,
- list: [],
- };
- return res;
- }
- throw e;
- }),
- });
-};
+export type WithUsername = Pick<APISIXType['Consumer'], 'username'>;
-export const getCredentialQueryOptions = (username: string, id: string) =>
- queryOptions({
- queryKey: ['credential', username, id],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespCredentialDetail']>(
- `${API_CREDENTIALS(username)}/${id}`
- )
- .then((v) => v.data),
- });
+export const getCredentialListReq = (req: AxiosInstance, params: WithUsername) =>
+ req
+ .get<unknown, APISIXType['RespCredentialList']>(
+ API_CREDENTIALS(params.username),
+ {
+ headers: {
+ [SKIP_INTERCEPTOR_HEADER]: ['404'],
+ },
+ params,
+ }
+ )
+ .then((v) => v.data)
+ .catch((e) => {
+ // 404 means credentials is empty
+ if (e.response.status === 404) {
+ const res: APISIXListResponse<APISIXType['Credential']> = {
+ total: 0,
+ list: [],
+ };
+ return res;
+ }
+ throw e;
+ });
+
+export const getCredentialReq = (req: AxiosInstance, username: string, id: string) =>
+ req
+ .get<unknown, APISIXType['RespCredentialDetail']>(
+ `${API_CREDENTIALS(username)}/${id}`
+ )
+ .then((v) => v.data);
export const putCredentialReq = (
+ req: AxiosInstance,
data: APISIXType['CredentialPut'] & WithUsername
) => {
const { username, id, ...rest } = data;
diff --git a/src/apis/global_rules.ts b/src/apis/global_rules.ts
new file mode 100644
index 0000000..4572f7a
--- /dev/null
+++ b/src/apis/global_rules.ts
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { AxiosInstance } from 'axios';
+
+import { API_GLOBAL_RULES } from '@/config/constant';
+import type { APISIXType } from '@/types/schema/apisix';
+
+export const getGlobalRuleListReq = (req: AxiosInstance) =>
+ req
+ .get<unknown, APISIXType['RespGlobalRuleList']>(API_GLOBAL_RULES)
+ .then((v) => v.data);
+
+export const getGlobalRuleReq = (req: AxiosInstance, id: string) =>
+ req
+ .get<unknown, APISIXType['RespGlobalRuleDetail']>(
+ `${API_GLOBAL_RULES}/${id}`
+ )
+ .then((v) => v.data);
+
+export const putGlobalRuleReq = (
+ req: AxiosInstance,
+ data: APISIXType['GlobalRulePut']
+) => {
+ const { id, ...rest } = data;
+ return req.put<
+ APISIXType['GlobalRulePut'],
+ APISIXType['RespGlobalRuleDetail']
+ >(`${API_GLOBAL_RULES}/${id}`, rest);
+};
diff --git a/src/apis/hooks.ts b/src/apis/hooks.ts
index f1e6d56..118fa6b 100644
--- a/src/apis/hooks.ts
+++ b/src/apis/hooks.ts
@@ -15,47 +15,208 @@
* limitations under the License.
*/
import { queryOptions, useSuspenseQuery } from '@tanstack/react-query';
+import type { AxiosInstance } from 'axios';
-import { getUpstreamListReq } from '@/apis/upstreams';
+import { getRouteListReq, getRouteReq } from '@/apis/routes';
+import { getUpstreamListReq, getUpstreamReq } from '@/apis/upstreams';
import { req } from '@/config/req';
+import type {
+ APISIXDetailResponse,
+ APISIXListResponse,
+} from '@/types/schema/apisix/type';
import { type PageSearchType } from '@/types/schema/pageSearch';
import { useSearchParams } from '@/utils/useSearchParams';
-import { useTablePagination } from '@/utils/useTablePagination';
+import {
+ type ListPageKeys,
+ useTablePagination,
+} from '@/utils/useTablePagination';
-import { getRouteListReq, getRouteReq } from './routes';
+import {
+ getConsumerGroupListReq,
+ getConsumerGroupReq,
+} from './consumer_groups';
+import { getConsumerListReq, getConsumerReq } from './consumers';
+import { getCredentialListReq, getCredentialReq } from './credentials';
+import { getGlobalRuleListReq, getGlobalRuleReq } from './global_rules';
+import { getPluginConfigListReq, getPluginConfigReq } from './plugin_configs';
+import { getProtoListReq, getProtoReq } from './protos';
+import { getSecretListReq, getSecretReq } from './secrets';
+import { getServiceListReq, getServiceReq } from './services';
+import { getSSLListReq, getSSLReq } from './ssls';
+import { getStreamRouteListReq, getStreamRouteReq } from './stream_routes';
-export const getUpstreamListQueryOptions = (props: PageSearchType) => {
+const genDetailQueryOptions =
+ <T extends unknown[], R>(
+ key: string,
+ getDetailReq: (
+ req: AxiosInstance,
+ ...args: T
+ ) => Promise<APISIXDetailResponse<R>>
+ ) =>
+ (...args: T) => {
+ return queryOptions({
+ queryKey: [key, ...args],
+ queryFn: () => getDetailReq(req, ...args),
+ });
+ };
+/** simple factory func for list query options which support extends PageSearchType */
+const genListQueryOptions =
+ <P extends PageSearchType, R>(
+ key: string,
+ listReq: (req: AxiosInstance, props: P) => Promise<APISIXListResponse<R>>
+ ) =>
+ (props: P) => {
+ return queryOptions({
+ queryKey: [key, props],
+ queryFn: () => listReq(req, props),
+ });
+ };
+
+/** simple hook factory func for list hooks which support extends PageSearchType */
+export const genUseList = <T extends ListPageKeys, P extends PageSearchType, R>(
+ routeId: T,
+ listQueryOptions: ReturnType<typeof genListQueryOptions<P, R>>
+) => {
+ return () => {
+ const { params, setParams } = useSearchParams<T, P>(routeId);
+ const listQuery = useSuspenseQuery(listQueryOptions(params));
+ const { data, isLoading, refetch } = listQuery;
+ const opts = { data, setParams, params };
+ const pagination = useTablePagination(opts);
+ return { data, isLoading, refetch, pagination };
+ };
+};
+
+export const getUpstreamQueryOptions = genDetailQueryOptions(
+ 'upstream',
+ getUpstreamReq
+);
+export const getUpstreamListQueryOptions = genListQueryOptions(
+ 'upstreams',
+ getUpstreamListReq
+);
+export const useUpstreamList = genUseList(
+ '/upstreams/',
+ getUpstreamListQueryOptions
+);
+
+export const getRouteQueryOptions = genDetailQueryOptions('route', getRouteReq);
+export const getRouteListQueryOptions = genListQueryOptions(
+ 'routes',
+ getRouteListReq
+);
+export const useRouteList = genUseList('/routes/', getRouteListQueryOptions);
+
+export const getConsumerGroupQueryOptions = genDetailQueryOptions(
+ 'consumer_group',
+ getConsumerGroupReq
+);
+export const getConsumerGroupListQueryOptions = genListQueryOptions(
+ 'consumer_groups',
+ getConsumerGroupListReq
+);
+export const useConsumerGroupList = genUseList(
+ '/consumer_groups/',
+ getConsumerGroupListQueryOptions
+);
+
+export const getStreamRouteQueryOptions = genDetailQueryOptions(
+ 'stream_route',
+ getStreamRouteReq
+);
+export const getStreamRouteListQueryOptions = genListQueryOptions(
+ 'stream_routes',
+ getStreamRouteListReq
+);
+export const useStreamRouteList = genUseList(
+ '/stream_routes/',
+ getStreamRouteListQueryOptions
+);
+
+export const getServiceQueryOptions = genDetailQueryOptions(
+ 'service',
+ getServiceReq
+);
+export const getServiceListQueryOptions = genListQueryOptions(
+ 'services',
+ getServiceListReq
+);
+export const useServiceList = genUseList(
+ '/services/',
+ getServiceListQueryOptions
+);
+
+export const getGlobalRuleQueryOptions = genDetailQueryOptions(
+ 'global_rule',
+ getGlobalRuleReq
+);
+export const getGlobalRuleListQueryOptions = genListQueryOptions(
+ 'global_rules',
+ getGlobalRuleListReq
+);
+export const useGlobalRuleList = genUseList(
+ '/global_rules/',
+ getGlobalRuleListQueryOptions
+);
+
+export const getPluginConfigQueryOptions = genDetailQueryOptions(
+ 'plugin_config',
+ getPluginConfigReq
+);
+export const getPluginConfigListQueryOptions = genListQueryOptions(
+ 'plugin_configs',
+ getPluginConfigListReq
+);
+export const usePluginConfigList = genUseList(
+ '/plugin_configs/',
+ getPluginConfigListQueryOptions
+);
+
+export const getSSLQueryOptions = genDetailQueryOptions('ssl', getSSLReq);
+export const getSSLListQueryOptions = genListQueryOptions('ssls', getSSLListReq);
+export const useSSLList = genUseList('/ssls/', getSSLListQueryOptions);
+
+export const getConsumerQueryOptions = genDetailQueryOptions(
+ 'consumer',
+ getConsumerReq
+);
+export const getConsumerListQueryOptions = genListQueryOptions(
+ 'consumers',
+ getConsumerListReq
+);
+export const useConsumerList = genUseList(
+ '/consumers/',
+ getConsumerListQueryOptions
+);
+
+export const getCredentialQueryOptions = genDetailQueryOptions(
+ 'credential',
+ getCredentialReq
+);
+export const getCredentialListQueryOptions = (username: string) => {
return queryOptions({
- queryKey: ['upstreams', props.page, props.page_size],
- queryFn: () => getUpstreamListReq(req, props),
+ queryKey: ['credentials', username],
+ queryFn: () => getCredentialListReq(req, { username }),
});
};
-
-export const useUpstreamList = () => {
- const { params, setParams } = useSearchParams('/upstreams/');
- const upstreamQuery = useSuspenseQuery(getUpstreamListQueryOptions(params));
- const { data, isLoading, refetch } = upstreamQuery;
- const pagination = useTablePagination({ data, setParams, params });
- return { data, isLoading, refetch, pagination };
+export const useCredentialsList = (username: string) => {
+ const credentialQuery = useSuspenseQuery(
+ getCredentialListQueryOptions(username)
+ );
+ const { data, isLoading, refetch } = credentialQuery;
+ return { data, isLoading, refetch };
};
-export const getRouteListQueryOptions = (props: PageSearchType) => {
- return queryOptions({
- queryKey: ['routes', props.page, props.page_size],
- queryFn: () => getRouteListReq(req, props),
- });
-};
+export const getProtoQueryOptions = genDetailQueryOptions('proto', getProtoReq);
+export const getProtoListQueryOptions = genListQueryOptions('protos', getProtoListReq);
+export const useProtoList = genUseList('/protos/', getProtoListQueryOptions);
-export const useRouteList = () => {
- const { params, setParams } = useSearchParams('/routes/');
- const routeQuery = useSuspenseQuery(getRouteListQueryOptions(params));
- const { data, isLoading, refetch } = routeQuery;
- const pagination = useTablePagination({ data, setParams, params });
- return { data, isLoading, refetch, pagination };
-};
-
-export const getRouteQueryOptions = (id: string) =>
- queryOptions({
- queryKey: ['route', id],
- queryFn: () => getRouteReq(req, id),
- });
+export const getSecretQueryOptions = genDetailQueryOptions(
+ 'secret',
+ getSecretReq
+);
+export const getSecretListQueryOptions = genListQueryOptions(
+ 'secrets',
+ getSecretListReq
+);
+export const useSecretList = genUseList('/secrets/', getSecretListQueryOptions);
diff --git a/src/apis/plugin_configs.ts b/src/apis/plugin_configs.ts
index b873bc2..41d3d6a 100644
--- a/src/apis/plugin_configs.ts
+++ b/src/apis/plugin_configs.ts
@@ -14,38 +14,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { queryOptions } from '@tanstack/react-query';
+import type { AxiosInstance } from 'axios';
import { API_PLUGIN_CONFIGS } from '@/config/constant';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import type { PageSearchType } from '@/types/schema/pageSearch';
-export const getPluginConfigListQueryOptions = (props: PageSearchType) => {
- const { page, pageSize } = props;
- return queryOptions({
- queryKey: ['plugin_configs', page, pageSize],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespPluginConfigList']>(API_PLUGIN_CONFIGS, {
- params: { page, page_size: pageSize },
- })
- .then((v) => v.data),
- });
-};
+export const getPluginConfigListReq = (req: AxiosInstance, params: PageSearchType) =>
+ req
+ .get<unknown, APISIXType['RespPluginConfigList']>(API_PLUGIN_CONFIGS, {
+ params,
+ })
+ .then((v) => v.data);
-export const getPluginConfigQueryOptions = (id: string) =>
- queryOptions({
- queryKey: ['plugin_config', id],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespPluginConfigDetail']>(
- `${API_PLUGIN_CONFIGS}/${id}`
- )
- .then((v) => v.data),
- });
+export const getPluginConfigReq = (req: AxiosInstance, id: string) =>
+ req
+ .get<unknown, APISIXType['RespPluginConfigDetail']>(
+ `${API_PLUGIN_CONFIGS}/${id}`
+ )
+ .then((v) => v.data);
-export const putPluginConfigReq = (data: APISIXType['PluginConfigPut']) => {
+export const putPluginConfigReq = (
+ req: AxiosInstance,
+ data: APISIXType['PluginConfigPut']
+) => {
const { id, ...rest } = data;
return req.put<
APISIXType['PluginConfigPut'],
diff --git a/src/apis/plugins.ts b/src/apis/plugins.ts
index 7fcb9cc..8e14b34 100644
--- a/src/apis/plugins.ts
+++ b/src/apis/plugins.ts
@@ -19,7 +19,6 @@
import type { PluginConfig } from '@/components/form-slice/FormItemPlugins/PluginEditorDrawer';
import {
- API_GLOBAL_RULES,
API_PLUGIN_METADATA,
API_PLUGINS,
API_PLUGINS_LIST,
@@ -27,24 +26,6 @@
import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
-export const putGlobalRuleReq = (data: APISIXType['GlobalRulePut']) => {
- const { id, ...rest } = data;
- return req.put<
- APISIXType['GlobalRulePut'],
- APISIXType['RespGlobalRuleDetail']
- >(`${API_GLOBAL_RULES}/${id}`, rest);
-};
-
-export const getGlobalRuleQueryOptions = (id: string) =>
- queryOptions({
- queryKey: ['global_rule', id],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespGlobalRuleDetail']>(
- `${API_GLOBAL_RULES}/${id}`
- )
- .then((v) => v.data),
- });
export type NeedPluginSchema = {
schema: APISIXType['PluginSchemaKeys'];
diff --git a/src/apis/protos.ts b/src/apis/protos.ts
index 352e802..fe0e93d 100644
--- a/src/apis/protos.ts
+++ b/src/apis/protos.ts
@@ -14,39 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { queryOptions } from '@tanstack/react-query';
+import type { AxiosInstance } from 'axios';
import { API_PROTOS } from '@/config/constant';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import type { PageSearchType } from '@/types/schema/pageSearch';
-export const getProtoListQueryOptions = (props: PageSearchType) => {
- const { page, pageSize } = props;
- return queryOptions({
- queryKey: ['protos', page, pageSize],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespProtoList']>(API_PROTOS, {
- params: {
- page,
- page_size: pageSize,
- },
- })
- .then((v) => v.data),
- });
-};
+export const getProtoListReq = (req: AxiosInstance, params: PageSearchType) =>
+ req
+ .get<unknown, APISIXType['RespProtoList']>(API_PROTOS, {
+ params,
+ })
+ .then((v) => v.data);
-export const getProtoQueryOptions = (id: string) =>
- queryOptions({
- queryKey: ['proto', id],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespProtoDetail']>(`${API_PROTOS}/${id}`)
- .then((v) => v.data),
- });
+export const getProtoReq = (req: AxiosInstance, id: string) =>
+ req
+ .get<unknown, APISIXType['RespProtoDetail']>(`${API_PROTOS}/${id}`)
+ .then((v) => v.data);
-export const putProtoReq = (data: APISIXType['Proto']) => {
+export const putProtoReq = (req: AxiosInstance, data: APISIXType['Proto']) => {
const { id, ...rest } = data;
return req.put<APISIXType['Proto'], APISIXType['RespProtoDetail']>(
`${API_PROTOS}/${id}`,
@@ -54,7 +40,10 @@
);
};
-export const postProtoReq = (data: APISIXType['ProtoPost']) => {
+export const postProtoReq = (
+ req: AxiosInstance,
+ data: APISIXType['ProtoPost']
+) => {
return req.post<APISIXType['ProtoPost'], APISIXType['RespProtoList']>(
API_PROTOS,
data
diff --git a/src/apis/routes.ts b/src/apis/routes.ts
index c541bf7..2eeadac 100644
--- a/src/apis/routes.ts
+++ b/src/apis/routes.ts
@@ -46,7 +46,6 @@
const res = await getRouteListReq(req, {
page: 1,
page_size: 1000,
- pageSize: 1000,
});
if (res.total === 0) return;
return await Promise.all(
diff --git a/src/apis/secrets.ts b/src/apis/secrets.ts
index d3f5e40..46ec643 100644
--- a/src/apis/secrets.ts
+++ b/src/apis/secrets.ts
@@ -14,10 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { queryOptions } from '@tanstack/react-query';
+import type { AxiosInstance } from 'axios';
import { API_SECRETS } from '@/config/constant';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import type { PageSearchType } from '@/types/schema/pageSearch';
@@ -37,41 +36,35 @@
return { ...data, value: { ...data.value, manager, id: realId } };
};
-export const getSecretListQueryOptions = (props: PageSearchType) => {
- const { page, pageSize } = props;
- return queryOptions({
- queryKey: ['secrets', page, pageSize],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespSecretList']>(API_SECRETS, {
- params: { page, page_size: pageSize },
- })
- .then((v) => {
- const { list, ...rest } = v.data;
- return {
- ...rest,
- list: list.map(preParseSecretItem),
- };
- }),
- });
-};
+export const getSecretListReq = (req: AxiosInstance, params: PageSearchType) =>
+ req
+ .get<unknown, APISIXType['RespSecretList']>(API_SECRETS, {
+ params,
+ })
+ .then((v) => {
+ const { list, ...rest } = v.data;
+ return {
+ ...rest,
+ list: list.map(preParseSecretItem),
+ };
+ });
-export const getSecretQueryOptions = (
+export const getSecretReq = (
+ req: AxiosInstance,
props: Pick<APISIXType['Secret'], 'id' | 'manager'>
) => {
const { id, manager } = props;
- return queryOptions({
- queryKey: ['secret', manager, id],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespSecretDetail']>(
- `${API_SECRETS}/${manager}/${id}`
- )
- .then((v) => preParseSecretItem(v.data)),
- });
+ return req
+ .get<unknown, APISIXType['RespSecretDetail']>(
+ `${API_SECRETS}/${manager}/${id}`
+ )
+ .then((v) => preParseSecretItem(v.data));
};
-export const putSecretReq = (data: APISIXType['Secret']) => {
+export const putSecretReq = (
+ req: AxiosInstance,
+ data: APISIXType['Secret']
+) => {
const { manager, id, ...rest } = data;
return req.put<APISIXType['Secret'], APISIXType['RespSecretDetail']>(
`${API_SECRETS}/${manager}/${id}`,
diff --git a/src/apis/services.ts b/src/apis/services.ts
index 5918879..dd7eb9a 100644
--- a/src/apis/services.ts
+++ b/src/apis/services.ts
@@ -14,38 +14,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { queryOptions } from '@tanstack/react-query';
+import type { AxiosInstance } from 'axios';
import { API_SERVICES } from '@/config/constant';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import type { PageSearchType } from '@/types/schema/pageSearch';
export type ServicePostType = APISIXType['ServicePost'];
-export const getServiceListQueryOptions = (props: PageSearchType) => {
- const { page, pageSize } = props;
- return queryOptions({
- queryKey: ['services', page, pageSize],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespServiceList']>(API_SERVICES, {
- params: { page, page_size: pageSize },
- })
- .then((v) => v.data),
- });
-};
+export const getServiceListReq = (req: AxiosInstance, params: PageSearchType) =>
+ req
+ .get<unknown, APISIXType['RespServiceList']>(API_SERVICES, {
+ params,
+ })
+ .then((v) => v.data);
-export const getServiceQueryOptions = (id: string) =>
- queryOptions({
- queryKey: ['service', id],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespServiceDetail']>(`${API_SERVICES}/${id}`)
- .then((v) => v.data),
- });
+export const getServiceReq = (req: AxiosInstance, id: string) =>
+ req
+ .get<unknown, APISIXType['RespServiceDetail']>(`${API_SERVICES}/${id}`)
+ .then((v) => v.data);
-export const putServiceReq = (data: APISIXType['Service']) => {
+export const putServiceReq = (
+ req: AxiosInstance,
+ data: APISIXType['Service']
+) => {
const { id, ...rest } = data;
return req.put<APISIXType['Service'], APISIXType['RespServiceDetail']>(
`${API_SERVICES}/${id}`,
@@ -53,7 +45,7 @@
);
};
-export const postServiceReq = (data: ServicePostType) =>
+export const postServiceReq = (req: AxiosInstance, data: ServicePostType) =>
req.post<ServicePostType, APISIXType['RespServiceDetail']>(
API_SERVICES,
data
diff --git a/src/apis/ssls.ts b/src/apis/ssls.ts
index 89e3caf..4499fd8 100644
--- a/src/apis/ssls.ts
+++ b/src/apis/ssls.ts
@@ -14,42 +14,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { queryOptions } from '@tanstack/react-query';
+import type { AxiosInstance } from 'axios';
+import type { SSLPostType } from '@/components/form-slice/FormPartSSL/schema';
import { API_SSLS } from '@/config/constant';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import type { PageSearchType } from '@/types/schema/pageSearch';
-export const getSSLListQueryOptions = (props: PageSearchType) => {
- const { page, pageSize } = props;
- return queryOptions({
- queryKey: ['ssls', page, pageSize],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespSSLList']>(API_SSLS, {
- params: {
- page,
- page_size: pageSize,
- },
- })
- .then((v) => v.data),
- });
-};
+export const getSSLListReq = (req: AxiosInstance, params: PageSearchType) =>
+ req
+ .get<unknown, APISIXType['RespSSLList']>(API_SSLS, {
+ params,
+ })
+ .then((v) => v.data);
-export const getSSLDetailQueryOptions = (id: string) =>
- queryOptions({
- queryKey: ['ssl', id],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespSSLDetail']>(`${API_SSLS}/${id}`)
- .then((v) => v.data),
- });
+export const getSSLReq = (req: AxiosInstance, id: string) =>
+ req
+ .get<unknown, APISIXType['RespSSLDetail']>(`${API_SSLS}/${id}`)
+ .then((v) => v.data);
-export const putSSLReq = (data: APISIXType['SSL']) => {
+export const putSSLReq = (req: AxiosInstance, data: APISIXType['SSL']) => {
const { id, ...rest } = data;
return req.put<APISIXType['SSL'], APISIXType['RespSSLDetail']>(
`${API_SSLS}/${id}`,
rest
);
};
+
+export const postSSLReq = (req: AxiosInstance, data: SSLPostType) =>
+ req.post<APISIXType['SSL'], APISIXType['RespSSLDetail']>(API_SSLS, data);
diff --git a/src/apis/stream_routes.ts b/src/apis/stream_routes.ts
index 2f57af4..0e26ae2 100644
--- a/src/apis/stream_routes.ts
+++ b/src/apis/stream_routes.ts
@@ -14,39 +14,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { queryOptions } from '@tanstack/react-query';
+
+import type { AxiosInstance } from 'axios';
import type { StreamRoutePostType } from '@/components/form-slice/FormPartStreamRoute/schema';
import { API_STREAM_ROUTES } from '@/config/constant';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import type { PageSearchType } from '@/types/schema/pageSearch';
-export const getStreamRouteListQueryOptions = (props: PageSearchType) => {
- const { page, pageSize } = props;
- return queryOptions({
- queryKey: ['stream_routes', page, pageSize],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespStreamRouteList']>(API_STREAM_ROUTES, {
- params: { page, page_size: pageSize },
- })
- .then((v) => v.data),
- });
-};
+export const getStreamRouteListReq = (req: AxiosInstance, params: PageSearchType) =>
+ req
+ .get<unknown, APISIXType['RespStreamRouteList']>(API_STREAM_ROUTES, {
+ params,
+ })
+ .then((v) => v.data);
-export const getStreamRouteQueryOptions = (id: string) =>
- queryOptions({
- queryKey: ['stream_route', id],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespStreamRouteDetail']>(
- `${API_STREAM_ROUTES}/${id}`
- )
- .then((v) => v.data),
- });
+export const getStreamRouteReq = (req: AxiosInstance, id: string) =>
+ req
+ .get<unknown, APISIXType['RespStreamRouteDetail']>(
+ `${API_STREAM_ROUTES}/${id}`
+ )
+ .then((v) => v.data);
-export const putStreamRouteReq = (data: APISIXType['StreamRoute']) => {
+export const putStreamRouteReq = (
+ req: AxiosInstance,
+ data: APISIXType['StreamRoute']
+) => {
const { id, ...rest } = data;
return req.put<
APISIXType['StreamRoute'],
@@ -54,7 +47,10 @@
>(`${API_STREAM_ROUTES}/${id}`, rest);
};
-export const postStreamRouteReq = (data: StreamRoutePostType) =>
+export const postStreamRouteReq = (
+ req: AxiosInstance,
+ data: StreamRoutePostType
+) =>
req.post<unknown, APISIXType['RespStreamRouteDetail']>(
API_STREAM_ROUTES,
data
diff --git a/src/apis/upstreams.ts b/src/apis/upstreams.ts
index 1938b38..a7f4848 100644
--- a/src/apis/upstreams.ts
+++ b/src/apis/upstreams.ts
@@ -55,7 +55,6 @@
const res = await getUpstreamListReq(req, {
page: 1,
page_size: 1000,
- pageSize: 1000,
});
if (res.total === 0) return;
return await Promise.all(
diff --git a/src/routes/consumer_groups/add.tsx b/src/routes/consumer_groups/add.tsx
index da57d00..1b09c9a 100644
--- a/src/routes/consumer_groups/add.tsx
+++ b/src/routes/consumer_groups/add.tsx
@@ -27,7 +27,8 @@
import { FormPartPluginConfig } from '@/components/form-slice/FormPartPluginConfig';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import PageHeader from '@/components/page/PageHeader';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
const ConsumerGroupAddForm = () => {
@@ -35,7 +36,8 @@
const router = useRouter();
const putConsumerGroup = useMutation({
- mutationFn: putConsumerGroupReq,
+ mutationFn: (d: APISIXType['ConsumerGroupPut']) =>
+ putConsumerGroupReq(req, d),
async onSuccess(response) {
notifications.show({
message: t('info.add.success', { name: t('consumerGroups.singular') }),
diff --git a/src/routes/consumer_groups/detail.$id.tsx b/src/routes/consumer_groups/detail.$id.tsx
index 497c100..c306a22 100644
--- a/src/routes/consumer_groups/detail.$id.tsx
+++ b/src/routes/consumer_groups/detail.$id.tsx
@@ -28,17 +28,16 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import {
- getConsumerGroupQueryOptions,
- putConsumerGroupReq,
-} from '@/apis/consumer_groups';
+import { putConsumerGroupReq } from '@/apis/consumer_groups';
+import { getConsumerGroupQueryOptions } from '@/apis/hooks';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartPluginConfig } from '@/components/form-slice/FormPartPluginConfig';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { API_CONSUMER_GROUPS } from '@/config/constant';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
type Props = {
@@ -55,7 +54,8 @@
const { data } = consumerGroupQuery;
const putConsumerGroup = useMutation({
- mutationFn: putConsumerGroupReq,
+ mutationFn: (d: APISIXType['ConsumerGroupPut']) =>
+ putConsumerGroupReq(req, d),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('consumerGroups.singular') }),
diff --git a/src/routes/consumer_groups/index.tsx b/src/routes/consumer_groups/index.tsx
index 747df0b..108ce06 100644
--- a/src/routes/consumer_groups/index.tsx
+++ b/src/routes/consumer_groups/index.tsx
@@ -16,12 +16,11 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
-import { useEffect, useMemo } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { getConsumerGroupListQueryOptions } from '@/apis/consumer_groups';
+import { getConsumerGroupListQueryOptions, useConsumerGroupList } from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn, ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
@@ -30,25 +29,10 @@
import { queryClient } from '@/config/global';
import type { APISIXType } from '@/types/schema/apisix';
import { pageSearchSchema } from '@/types/schema/pageSearch';
-import { usePagination } from '@/utils/usePagination';
function ConsumerGroupsList() {
const { t } = useTranslation();
-
- const { pagination, handlePageChange, updateTotal } = usePagination({
- queryKey: 'consumer_groups',
- });
-
- const consumerGroupsQuery = useSuspenseQuery(
- getConsumerGroupListQueryOptions(pagination)
- );
- const { data, isLoading, refetch } = consumerGroupsQuery;
-
- useEffect(() => {
- if (data?.total) {
- updateTotal(data.total);
- }
- }, [data?.total, updateTotal]);
+ const { data, isLoading, refetch, pagination } = useConsumerGroupList();
const columns = useMemo<
ProColumns<APISIXType['RespConsumerGroupItem']>[]
@@ -115,13 +99,7 @@
loading={isLoading}
search={false}
options={false}
- pagination={{
- current: pagination.page,
- pageSize: pagination.pageSize,
- total: pagination.total,
- showSizeChanger: true,
- onChange: handlePageChange,
- }}
+ pagination={pagination}
cardProps={{ bodyStyle: { padding: 0 } }}
toolbar={{
menu: {
diff --git a/src/routes/consumers/add.tsx b/src/routes/consumers/add.tsx
index c7e8adb..137cf69 100644
--- a/src/routes/consumers/add.tsx
+++ b/src/routes/consumers/add.tsx
@@ -26,7 +26,8 @@
import { FormPartConsumer } from '@/components/form-slice/FormPartConsumer';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import PageHeader from '@/components/page/PageHeader';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
const ConsumerAddForm = () => {
@@ -34,7 +35,7 @@
const router = useRouter();
const putConsumer = useMutation({
- mutationFn: putConsumerReq,
+ mutationFn: (d: APISIXType['ConsumerPut']) => putConsumerReq(req, d),
async onSuccess(_, res) {
notifications.show({
message: t('info.add.success', { name: t('consumers.singular') }),
diff --git a/src/routes/consumers/detail.$username/credentials/add.tsx b/src/routes/consumers/detail.$username/credentials/add.tsx
index f157bd8..d5f3dd8 100644
--- a/src/routes/consumers/detail.$username/credentials/add.tsx
+++ b/src/routes/consumers/detail.$username/credentials/add.tsx
@@ -28,7 +28,8 @@
import { FormTOCBox } from '@/components/form-slice/FormSection';
import PageHeader from '@/components/page/PageHeader';
import { DetailCredentialsTabs } from '@/components/page-slice/consumers/DetailCredentialsTabs';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
const CredentialAddForm = () => {
@@ -39,7 +40,8 @@
});
const putCredential = useMutation({
- mutationFn: putCredentialReq,
+ mutationFn: (d: APISIXType['CredentialPut']) =>
+ putCredentialReq(req, pipeProduce()({ ...d, username })),
async onSuccess(_, res) {
notifications.show({
message: t('info.add.success', {
@@ -66,11 +68,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) =>
- putCredential.mutateAsync({ username, ...pipeProduce()(d) })
- )}
- >
+ <form onSubmit={form.handleSubmit((d) => putCredential.mutateAsync(d))}>
<FormPartCredential />
<FormSubmitBtn>{t('form.btn.add')}</FormSubmitBtn>
</form>
diff --git a/src/routes/consumers/detail.$username/credentials/detail.$id.tsx b/src/routes/consumers/detail.$username/credentials/detail.$id.tsx
index f13235a..d848bce 100644
--- a/src/routes/consumers/detail.$username/credentials/detail.$id.tsx
+++ b/src/routes/consumers/detail.$username/credentials/detail.$id.tsx
@@ -28,10 +28,8 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import {
- getCredentialQueryOptions,
- putCredentialReq,
-} from '@/apis/credentials';
+import { putCredentialReq } from '@/apis/credentials';
+import { getCredentialQueryOptions } from '@/apis/hooks';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartCredential } from '@/components/form-slice/FormPartCredential';
import { FormTOCBox } from '@/components/form-slice/FormSection';
@@ -39,7 +37,8 @@
import PageHeader from '@/components/page/PageHeader';
import { DetailCredentialsTabs } from '@/components/page-slice/consumers/DetailCredentialsTabs';
import { API_CREDENTIALS } from '@/config/constant';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
type CredentialFormProps = {
@@ -75,7 +74,8 @@
}, [credentialData, form, isLoading]);
const putCredential = useMutation({
- mutationFn: putCredentialReq,
+ mutationFn: (d: APISIXType['CredentialPut']) =>
+ putCredentialReq(req, pipeProduce()({ ...d, username })),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('credentials.singular') }),
@@ -92,14 +92,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) => {
- putCredential.mutateAsync({
- username,
- ...pipeProduce()(d),
- });
- })}
- >
+ <form onSubmit={form.handleSubmit((d) => putCredential.mutateAsync(d))}>
<FormPartCredential showDate />
{!readOnly && (
<Group>
diff --git a/src/routes/consumers/detail.$username/credentials/index.tsx b/src/routes/consumers/detail.$username/credentials/index.tsx
index ff02919..d331ec2 100644
--- a/src/routes/consumers/detail.$username/credentials/index.tsx
+++ b/src/routes/consumers/detail.$username/credentials/index.tsx
@@ -16,12 +16,14 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute, useParams } from '@tanstack/react-router';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { getCredentialListQueryOptions } from '@/apis/credentials';
+import {
+ getCredentialListQueryOptions,
+ useCredentialsList,
+} from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn, ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
@@ -36,11 +38,7 @@
const { username } = useParams({
from: '/consumers/detail/$username/credentials/',
});
-
- const credentialsQuery = useSuspenseQuery(
- getCredentialListQueryOptions({ username })
- );
- const { data, isLoading, refetch } = credentialsQuery;
+ const { data, isLoading, refetch } = useCredentialsList(username);
const columns = useMemo<
ProColumns<APISIXType['RespCredentialItem']>[]
@@ -142,10 +140,8 @@
);
}
-export const Route = createFileRoute(
- '/consumers/detail/$username/credentials/'
-)({
+export const Route = createFileRoute('/consumers/detail/$username/credentials/')({
component: RouteComponent,
loader: ({ params }) =>
- queryClient.ensureQueryData(getCredentialListQueryOptions(params)),
+ queryClient.ensureQueryData(getCredentialListQueryOptions(params.username)),
});
diff --git a/src/routes/consumers/detail.$username/index.tsx b/src/routes/consumers/detail.$username/index.tsx
index b44ec41..e7585dd 100644
--- a/src/routes/consumers/detail.$username/index.tsx
+++ b/src/routes/consumers/detail.$username/index.tsx
@@ -28,7 +28,8 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import { getConsumerQueryOptions, putConsumerReq } from '@/apis/consumers';
+import { putConsumerReq } from '@/apis/consumers';
+import { getConsumerQueryOptions } from '@/apis/hooks';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartConsumer } from '@/components/form-slice/FormPartConsumer';
import { FormTOCBox } from '@/components/form-slice/FormSection';
@@ -37,7 +38,8 @@
import PageHeader from '@/components/page/PageHeader';
import { DetailCredentialsTabs } from '@/components/page-slice/consumers/DetailCredentialsTabs';
import { API_CONSUMERS } from '@/config/constant';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
type Props = {
@@ -68,7 +70,7 @@
}, [consumerData, form, isLoading]);
const putConsumer = useMutation({
- mutationFn: putConsumerReq,
+ mutationFn: (d: APISIXType['ConsumerPut']) => putConsumerReq(req, d),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('consumers.singular') }),
diff --git a/src/routes/consumers/index.tsx b/src/routes/consumers/index.tsx
index 2663e24..b431ed3 100644
--- a/src/routes/consumers/index.tsx
+++ b/src/routes/consumers/index.tsx
@@ -16,12 +16,11 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
-import { useEffect, useMemo } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { getConsumerListQueryOptions } from '@/apis/consumers';
+import { getConsumerListQueryOptions, useConsumerList } from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn, ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
@@ -29,28 +28,11 @@
import { API_CONSUMERS } from '@/config/constant';
import { queryClient } from '@/config/global';
import type { APISIXType } from '@/types/schema/apisix';
-import {
- pageSearchSchema,
-} from '@/types/schema/pageSearch';
-import { usePagination } from '@/utils/usePagination';
+import { pageSearchSchema } from '@/types/schema/pageSearch';
function ConsumersList() {
const { t } = useTranslation();
-
- const { pagination, handlePageChange, updateTotal } = usePagination({
- queryKey: 'consumers',
- });
-
- const consumersQuery = useSuspenseQuery(
- getConsumerListQueryOptions(pagination)
- );
- const { data, isLoading, refetch } = consumersQuery;
-
- useEffect(() => {
- if (data?.total) {
- updateTotal(data.total);
- }
- }, [data?.total, updateTotal]);
+ const { data, isLoading, refetch, pagination } = useConsumerList();
const columns = useMemo<ProColumns<APISIXType['RespConsumerItem']>[]>(() => {
return [
@@ -109,13 +91,7 @@
loading={isLoading}
search={false}
options={false}
- pagination={{
- current: pagination.page,
- pageSize: pagination.pageSize,
- total: pagination.total,
- showSizeChanger: true,
- onChange: handlePageChange,
- }}
+ pagination={pagination}
cardProps={{ bodyStyle: { padding: 0 } }}
toolbar={{
menu: {
diff --git a/src/routes/global_rules/add.tsx b/src/routes/global_rules/add.tsx
index ff59f4a..3f0641f 100644
--- a/src/routes/global_rules/add.tsx
+++ b/src/routes/global_rules/add.tsx
@@ -25,11 +25,12 @@
import { FormProvider, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
-import { putGlobalRuleReq } from '@/apis/plugins';
+import { putGlobalRuleReq } from '@/apis/global_rules';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartGlobalRules } from '@/components/form-slice/FormPartGlobalRules';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import PageHeader from '@/components/page/PageHeader';
+import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import { APISIX } from '@/types/schema/apisix';
@@ -38,7 +39,18 @@
const router = useReactRouter();
const putGlobalRule = useMutation({
- mutationFn: putGlobalRuleReq,
+ mutationFn: (d: APISIXType['GlobalRulePut']) => putGlobalRuleReq(req, d),
+ async onSuccess(res) {
+ notifications.show({
+ id: 'add-global_rule',
+ message: t('info.add.success', { name: t('globalRules.singular') }),
+ color: 'green',
+ });
+ await router.navigate({
+ to: '/global_rules/detail/$id',
+ params: { id: res.data.value.id },
+ });
+ },
});
const form = useForm({
@@ -52,22 +64,9 @@
mode: 'onChange',
});
- const submit = async (data: APISIXType['GlobalRulePut']) => {
- const res = await putGlobalRule.mutateAsync(data);
- notifications.show({
- id: 'add-global_rule',
- message: t('info.add.success', { name: t('globalRules.singular') }),
- color: 'green',
- });
- await router.navigate({
- to: '/global_rules/detail/$id',
- params: { id: res.data.value.id },
- });
- };
-
return (
<FormProvider {...form}>
- <form onSubmit={form.handleSubmit(submit)}>
+ <form onSubmit={form.handleSubmit((d) => putGlobalRule.mutateAsync(d))}>
<FormPartGlobalRules />
<FormSubmitBtn>{t('form.btn.add')}</FormSubmitBtn>
</form>
diff --git a/src/routes/global_rules/detail.$id.tsx b/src/routes/global_rules/detail.$id.tsx
index edc5bc0..8ea27f9 100644
--- a/src/routes/global_rules/detail.$id.tsx
+++ b/src/routes/global_rules/detail.$id.tsx
@@ -17,7 +17,7 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { Button, Group } from '@mantine/core';
import { notifications } from '@mantine/notifications';
-import { useMutation, useQuery } from '@tanstack/react-query';
+import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
import {
createFileRoute,
useNavigate,
@@ -28,15 +28,16 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import { getGlobalRuleQueryOptions, putGlobalRuleReq } from '@/apis/plugins';
+import { putGlobalRuleReq } from '@/apis/global_rules';
+import { getGlobalRuleQueryOptions } from '@/apis/hooks';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartGlobalRules } from '@/components/form-slice/FormPartGlobalRules';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { API_GLOBAL_RULES } from '@/config/constant';
-import type { APISIXType } from '@/types/schema/apisix';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
type Props = {
readOnly: boolean;
@@ -46,7 +47,7 @@
const { readOnly, setReadOnly } = props;
const { t } = useTranslation();
const { id } = useParams({ from: '/global_rules/detail/$id' });
- const detailReq = useQuery(getGlobalRuleQueryOptions(id));
+ const detailReq = useSuspenseQuery(getGlobalRuleQueryOptions(id));
const form = useForm({
resolver: zodResolver(APISIX.GlobalRulePut),
@@ -63,22 +64,21 @@
}
}, [detailReq.data, form]);
- const putglobalRule = useMutation({
- mutationFn: putGlobalRuleReq,
+ const putGlobalRule = useMutation({
+ mutationFn: (d: APISIXType['GlobalRulePut']) => putGlobalRuleReq(req, d),
+ async onSuccess() {
+ notifications.show({
+ message: t('info.edit.success', { name: t('globalRules.singular') }),
+ color: 'green',
+ });
+ await detailReq.refetch();
+ setReadOnly(true);
+ },
});
- const submit = async (data: APISIXType['GlobalRulePut']) => {
- await putglobalRule.mutateAsync(data);
- notifications.show({
- message: t('info.edit.success', { name: t('globalRules.singular') }),
- color: 'green',
- });
- await detailReq.refetch();
- setReadOnly(true);
- };
return (
<FormProvider {...form}>
- <form onSubmit={form.handleSubmit(submit)}>
+ <form onSubmit={form.handleSubmit((d) => putGlobalRule.mutateAsync(d))}>
<FormPartGlobalRules />
{!readOnly && (
<Group>
diff --git a/src/routes/global_rules/index.tsx b/src/routes/global_rules/index.tsx
index ec5a9c6..248455e 100644
--- a/src/routes/global_rules/index.tsx
+++ b/src/routes/global_rules/index.tsx
@@ -16,59 +16,36 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { queryOptions, useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
-import { useEffect, useMemo } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
+import { getGlobalRuleListQueryOptions, useGlobalRuleList } from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn, ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
import { AntdConfigProvider } from '@/config/antdConfigProvider';
import { API_GLOBAL_RULES } from '@/config/constant';
import { queryClient } from '@/config/global';
-import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
-import {
- pageSearchSchema,
- type PageSearchType,
-} from '@/types/schema/pageSearch';
-import { usePagination } from '@/utils/usePagination';
+import { pageSearchSchema } from '@/types/schema/pageSearch';
-const genGlobalRulesQueryOptions = (props: PageSearchType) => {
- const { page, pageSize } = props;
- return queryOptions({
- queryKey: ['global_rules', page, pageSize],
- queryFn: () =>
- req
- .get<unknown, APISIXType['RespGlobalRuleList']>(API_GLOBAL_RULES, {
- params: {
- page,
- page_size: pageSize,
- },
- })
- .then((v) => v.data),
- });
-};
+
function RouteComponent() {
const { t } = useTranslation();
- // Use the pagination hook
- const { pagination, handlePageChange, updateTotal } = usePagination({
- queryKey: 'global_rules',
- });
-
- const globalRulesQuery = useSuspenseQuery(
- genGlobalRulesQueryOptions(pagination)
+ return (
+ <>
+ <PageHeader title={t('sources.globalRules')} />
+ <GlobalRulesList />
+ </>
);
- const { data, isLoading, refetch } = globalRulesQuery;
+}
- useEffect(() => {
- if (data?.total) {
- updateTotal(data.total);
- }
- }, [data?.total, updateTotal]);
+function GlobalRulesList() {
+ const { t } = useTranslation();
+ const { data, isLoading, refetch, pagination } = useGlobalRuleList();
const columns = useMemo<
ProColumns<APISIXType['RespConsumerGroupItem']>[]
@@ -104,46 +81,37 @@
}, [t, refetch]);
return (
- <>
- <PageHeader title={t('sources.globalRules')} />
- <AntdConfigProvider>
- <ProTable
- columns={columns}
- dataSource={data?.list || []}
- rowKey="id"
- loading={isLoading}
- search={false}
- options={false}
- pagination={{
- current: pagination.page,
- pageSize: pagination.pageSize,
- total: pagination.total,
- showSizeChanger: true,
- onChange: handlePageChange,
- }}
- cardProps={{ bodyStyle: { padding: 0 } }}
- toolbar={{
- menu: {
- type: 'inline',
- items: [
- {
- key: 'add',
- label: (
- <ToAddPageBtn
- key="add"
- to="/global_rules/add"
- label={t('info.add.title', {
- name: t('globalRules.singular'),
- })}
- />
- ),
- },
- ],
- },
- }}
- />
- </AntdConfigProvider>
- </>
+ <AntdConfigProvider>
+ <ProTable
+ columns={columns}
+ dataSource={data.list}
+ rowKey="id"
+ loading={isLoading}
+ search={false}
+ options={false}
+ pagination={pagination}
+ cardProps={{ bodyStyle: { padding: 0 } }}
+ toolbar={{
+ menu: {
+ type: 'inline',
+ items: [
+ {
+ key: 'add',
+ label: (
+ <ToAddPageBtn
+ key="add"
+ to="/global_rules/add"
+ label={t('info.add.title', {
+ name: t('globalRules.singular'),
+ })}
+ />
+ ),
+ },
+ ],
+ },
+ }}
+ />
+ </AntdConfigProvider>
);
}
@@ -152,5 +120,5 @@
validateSearch: pageSearchSchema,
loaderDeps: ({ search }) => search,
loader: ({ deps }) =>
- queryClient.ensureQueryData(genGlobalRulesQueryOptions(deps)),
+ queryClient.ensureQueryData(getGlobalRuleListQueryOptions(deps)),
});
diff --git a/src/routes/plugin_configs/add.tsx b/src/routes/plugin_configs/add.tsx
index dca90c2..4f4ea71 100644
--- a/src/routes/plugin_configs/add.tsx
+++ b/src/routes/plugin_configs/add.tsx
@@ -27,7 +27,8 @@
import { FormPartPluginConfig } from '@/components/form-slice/FormPartPluginConfig';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import PageHeader from '@/components/page/PageHeader';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
const PluginConfigAddForm = () => {
@@ -35,7 +36,8 @@
const router = useRouter();
const putPluginConfig = useMutation({
- mutationFn: putPluginConfigReq,
+ mutationFn: (d: APISIXType['PluginConfigPut']) =>
+ putPluginConfigReq(req, d),
async onSuccess(response) {
notifications.show({
message: t('info.add.success', { name: t('pluginConfigs.singular') }),
diff --git a/src/routes/plugin_configs/detail.$id.tsx b/src/routes/plugin_configs/detail.$id.tsx
index d882b9f..431dc2c 100644
--- a/src/routes/plugin_configs/detail.$id.tsx
+++ b/src/routes/plugin_configs/detail.$id.tsx
@@ -28,17 +28,16 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import {
- getPluginConfigQueryOptions,
- putPluginConfigReq,
-} from '@/apis/plugin_configs';
+import { getPluginConfigQueryOptions } from '@/apis/hooks';
+import { putPluginConfigReq } from '@/apis/plugin_configs';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartPluginConfig } from '@/components/form-slice/FormPartPluginConfig';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { API_PLUGIN_CONFIGS } from '@/config/constant';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
type Props = {
@@ -56,7 +55,8 @@
const initialValue = data.value;
const putPluginConfig = useMutation({
- mutationFn: putPluginConfigReq,
+ mutationFn: (d: APISIXType['PluginConfigPut']) =>
+ putPluginConfigReq(req, pipeProduce()({ ...d, id })),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('pluginConfigs.singular') }),
@@ -84,11 +84,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) =>
- putPluginConfig.mutateAsync(pipeProduce()({ ...d, id }))
- )}
- >
+ <form onSubmit={form.handleSubmit((d) => putPluginConfig.mutateAsync(d))}>
<FormPartPluginConfig />
{!readOnly && (
<Group>
diff --git a/src/routes/plugin_configs/index.tsx b/src/routes/plugin_configs/index.tsx
index f646a1f..bccb898 100644
--- a/src/routes/plugin_configs/index.tsx
+++ b/src/routes/plugin_configs/index.tsx
@@ -16,12 +16,11 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
-import { useEffect, useMemo } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { getPluginConfigListQueryOptions } from '@/apis/plugin_configs';
+import { getPluginConfigListQueryOptions, usePluginConfigList } from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn, ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
@@ -30,25 +29,10 @@
import { queryClient } from '@/config/global';
import type { APISIXType } from '@/types/schema/apisix';
import { pageSearchSchema } from '@/types/schema/pageSearch';
-import { usePagination } from '@/utils/usePagination';
function PluginConfigsList() {
const { t } = useTranslation();
-
- const { pagination, handlePageChange, updateTotal } = usePagination({
- queryKey: 'plugin_configs',
- });
-
- const pluginConfigsQuery = useSuspenseQuery(
- getPluginConfigListQueryOptions(pagination)
- );
- const { data, isLoading, refetch } = pluginConfigsQuery;
-
- useEffect(() => {
- if (data?.total) {
- updateTotal(data.total);
- }
- }, [data?.total, updateTotal]);
+ const { data, isLoading, refetch, pagination } = usePluginConfigList();
const columns = useMemo<
ProColumns<APISIXType['RespPluginConfigItem']>[]
@@ -115,13 +99,7 @@
loading={isLoading}
search={false}
options={false}
- pagination={{
- current: pagination.page,
- pageSize: pagination.pageSize,
- total: pagination.total,
- showSizeChanger: true,
- onChange: handlePageChange,
- }}
+ pagination={pagination}
cardProps={{ bodyStyle: { padding: 0 } }}
toolbar={{
menu: {
diff --git a/src/routes/protos/add.tsx b/src/routes/protos/add.tsx
index b8d9813..798dac7 100644
--- a/src/routes/protos/add.tsx
+++ b/src/routes/protos/add.tsx
@@ -28,6 +28,7 @@
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartProto } from '@/components/form-slice/FormPartProto';
import PageHeader from '@/components/page/PageHeader';
+import { req } from '@/config/req';
import type { APISIXType } from '@/types/schema/apisix';
import { APISIXProtos } from '@/types/schema/apisix/protos';
@@ -40,7 +41,14 @@
const router = useReactRouter();
const postProto = useMutation({
- mutationFn: postProtoReq,
+ mutationFn: (d: APISIXType['ProtoPost']) => postProtoReq(req, d),
+ async onSuccess() {
+ notifications.show({
+ message: t('info.add.success', { name: t('protos.singular') }),
+ color: 'green',
+ });
+ await router.navigate({ to: '/protos' });
+ },
});
const form = useForm({
@@ -51,19 +59,9 @@
mode: 'onChange',
});
- const submit = async (data: APISIXType['ProtoPost']) => {
- await postProto.mutateAsync(data);
- notifications.show({
- id: 'add-proto',
- message: t('info.add.success', { name: t('protos.singular') }),
- color: 'green',
- });
- await router.navigate({ to: '/protos' });
- };
-
return (
<FormProvider {...form}>
- <form onSubmit={form.handleSubmit(submit)}>
+ <form onSubmit={form.handleSubmit((d) => postProto.mutateAsync(d))}>
<FormPartProto />
<FormSubmitBtn>{t('form.btn.add')}</FormSubmitBtn>
</form>
diff --git a/src/routes/protos/detail.$id.tsx b/src/routes/protos/detail.$id.tsx
index 8834640..7035a93 100644
--- a/src/routes/protos/detail.$id.tsx
+++ b/src/routes/protos/detail.$id.tsx
@@ -28,7 +28,8 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import { getProtoQueryOptions, putProtoReq } from '@/apis/protos';
+import { getProtoQueryOptions } from '@/apis/hooks';
+import { putProtoReq } from '@/apis/protos';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartProto } from '@/components/form-slice/FormPartProto';
import { FormTOCBox } from '@/components/form-slice/FormSection';
@@ -36,6 +37,7 @@
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { API_PROTOS } from '@/config/constant';
+import { req } from '@/config/req';
import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
@@ -61,7 +63,7 @@
});
const putProto = useMutation({
- mutationFn: putProtoReq,
+ mutationFn: (d: APISIXType['Proto']) => putProtoReq(req, pipeProduce()(d)),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('protos.singular') }),
@@ -85,11 +87,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) =>
- putProto.mutateAsync(pipeProduce()(d))
- )}
- >
+ <form onSubmit={form.handleSubmit((d) => putProto.mutateAsync(d))}>
<FormSectionGeneral />
<FormPartProto allowUpload={!readOnly} />
{!readOnly && (
diff --git a/src/routes/protos/index.tsx b/src/routes/protos/index.tsx
index af84365..2754954 100644
--- a/src/routes/protos/index.tsx
+++ b/src/routes/protos/index.tsx
@@ -16,12 +16,11 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
-import { useEffect, useMemo } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { getProtoListQueryOptions } from '@/apis/protos';
+import { getProtoListQueryOptions, useProtoList } from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn, ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
@@ -30,24 +29,11 @@
import { queryClient } from '@/config/global';
import type { APISIXType } from '@/types/schema/apisix';
import { pageSearchSchema } from '@/types/schema/pageSearch';
-import { usePagination } from '@/utils/usePagination';
function RouteComponent() {
const { t } = useTranslation();
- // Use the pagination hook
- const { pagination, handlePageChange, updateTotal } = usePagination({
- queryKey: 'protos',
- });
-
- const protosQuery = useSuspenseQuery(getProtoListQueryOptions(pagination));
- const { data, isLoading, refetch } = protosQuery;
-
- useEffect(() => {
- if (data?.total) {
- updateTotal(data.total);
- }
- }, [data?.total, updateTotal]);
+ const { data, isLoading, refetch, pagination } = useProtoList();
const columns = useMemo<
ProColumns<APISIXType['RespProtoList']['data']['list'][number]>[]
@@ -93,13 +79,7 @@
loading={isLoading}
search={false}
options={false}
- pagination={{
- current: pagination.page,
- pageSize: pagination.pageSize,
- total: pagination.total,
- showSizeChanger: true,
- onChange: handlePageChange,
- }}
+ pagination={pagination}
cardProps={{ bodyStyle: { padding: 0 } }}
toolbar={{
menu: {
diff --git a/src/routes/secrets/add.tsx b/src/routes/secrets/add.tsx
index 83295d9..752b42e 100644
--- a/src/routes/secrets/add.tsx
+++ b/src/routes/secrets/add.tsx
@@ -28,7 +28,8 @@
import { FormTOCBox } from '@/components/form-slice/FormSection';
import { FormSectionGeneral } from '@/components/form-slice/FormSectionGeneral';
import PageHeader from '@/components/page/PageHeader';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
const SecretAddForm = () => {
@@ -36,7 +37,8 @@
const router = useRouter();
const putSecret = useMutation({
- mutationFn: putSecretReq,
+ mutationFn: (d: APISIXType['Secret']) =>
+ putSecretReq(req, pipeProduce()(d)),
async onSuccess() {
notifications.show({
message: t('info.add.success', { name: t('secrets.singular') }),
@@ -61,11 +63,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) =>
- putSecret.mutateAsync(pipeProduce()(d))
- )}
- >
+ <form onSubmit={form.handleSubmit((d) => putSecret.mutateAsync(d))}>
<FormSectionGeneral showDate={false} />
<FormPartSecret />
<FormSubmitBtn>{t('form.btn.add')}</FormSubmitBtn>
diff --git a/src/routes/secrets/detail.$manager.$id.tsx b/src/routes/secrets/detail.$manager.$id.tsx
index de6d5db..9c2e965 100644
--- a/src/routes/secrets/detail.$manager.$id.tsx
+++ b/src/routes/secrets/detail.$manager.$id.tsx
@@ -28,7 +28,8 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import { getSecretQueryOptions, putSecretReq } from '@/apis/secrets';
+import { getSecretQueryOptions } from '@/apis/hooks';
+import { putSecretReq } from '@/apis/secrets';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartSecret } from '@/components/form-slice/FormPartSecret';
import { FormTOCBox } from '@/components/form-slice/FormSection';
@@ -36,6 +37,7 @@
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { API_SECRETS } from '@/config/constant';
+import { req } from '@/config/req';
import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
@@ -73,7 +75,8 @@
}, [secretData, form, isLoading, readOnly]);
const putSecret = useMutation({
- mutationFn: putSecretReq,
+ mutationFn: (d: APISIXType['Secret']) =>
+ putSecretReq(req, pipeProduce()(d)),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('secrets.singular') }),
@@ -90,11 +93,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) => {
- putSecret.mutateAsync(pipeProduce()(d));
- })}
- >
+ <form onSubmit={form.handleSubmit((d) => putSecret.mutateAsync(d))}>
<FormSectionGeneral readOnly />
<FormPartSecret readOnlyManager />
{!readOnly && (
diff --git a/src/routes/secrets/index.tsx b/src/routes/secrets/index.tsx
index 18a7417..fa9810c 100644
--- a/src/routes/secrets/index.tsx
+++ b/src/routes/secrets/index.tsx
@@ -16,12 +16,11 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
-import { useEffect, useMemo } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { getSecretListQueryOptions } from '@/apis/secrets';
+import { getSecretListQueryOptions, useSecretList } from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn, ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
@@ -30,23 +29,10 @@
import { queryClient } from '@/config/global';
import type { APISIXType } from '@/types/schema/apisix';
import { pageSearchSchema } from '@/types/schema/pageSearch';
-import { usePagination } from '@/utils/usePagination';
function SecretList() {
const { t } = useTranslation();
-
- const { pagination, handlePageChange, updateTotal } = usePagination({
- queryKey: 'secrets',
- });
-
- const secretsQuery = useSuspenseQuery(getSecretListQueryOptions(pagination));
- const { data, isLoading, refetch } = secretsQuery;
-
- useEffect(() => {
- if (data?.total) {
- updateTotal(data.total);
- }
- }, [data?.total, updateTotal]);
+ const { data, isLoading, refetch, pagination } = useSecretList();
const columns = useMemo<
ProColumns<APISIXType['RespSecretList']['data']['list'][number]>[]
@@ -101,13 +87,7 @@
loading={isLoading}
search={false}
options={false}
- pagination={{
- current: pagination.page,
- pageSize: pagination.pageSize,
- total: pagination.total,
- showSizeChanger: true,
- onChange: handlePageChange,
- }}
+ pagination={pagination}
cardProps={{ bodyStyle: { padding: 0 } }}
toolbar={{
menu: {
diff --git a/src/routes/services/add.tsx b/src/routes/services/add.tsx
index 37b83ad..469e380 100644
--- a/src/routes/services/add.tsx
+++ b/src/routes/services/add.tsx
@@ -21,12 +21,13 @@
import { FormProvider, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
-import { postServiceReq } from '@/apis/services';
+import { postServiceReq, type ServicePostType } from '@/apis/services';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartService } from '@/components/form-slice/FormPartService';
import { ServicePostSchema } from '@/components/form-slice/FormPartService/schema';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import PageHeader from '@/components/page/PageHeader';
+import { req } from '@/config/req';
import { pipeProduce } from '@/utils/producer';
const ServiceAddForm = () => {
@@ -34,7 +35,7 @@
const router = useRouter();
const postService = useMutation({
- mutationFn: postServiceReq,
+ mutationFn: (d: ServicePostType) => postServiceReq(req, pipeProduce()(d)),
async onSuccess() {
notifications.show({
message: t('info.add.success', { name: t('services.singular') }),
@@ -53,11 +54,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) =>
- postService.mutateAsync(pipeProduce()(d))
- )}
- >
+ <form onSubmit={form.handleSubmit((d) => postService.mutateAsync(d))}>
<FormPartService />
<FormSubmitBtn>{t('form.btn.add')}</FormSubmitBtn>
</form>
diff --git a/src/routes/services/detail.$id.tsx b/src/routes/services/detail.$id.tsx
index 9c613f7..bf73a60 100644
--- a/src/routes/services/detail.$id.tsx
+++ b/src/routes/services/detail.$id.tsx
@@ -17,7 +17,7 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { Button, Group,Skeleton } from '@mantine/core';
import { notifications } from '@mantine/notifications';
-import { useMutation, useQuery } from '@tanstack/react-query';
+import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
import {
createFileRoute,
useNavigate,
@@ -28,7 +28,8 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import { getServiceQueryOptions, putServiceReq } from '@/apis/services';
+import { getServiceQueryOptions } from '@/apis/hooks';
+import { putServiceReq } from '@/apis/services';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartService } from '@/components/form-slice/FormPartService';
import { FormTOCBox } from '@/components/form-slice/FormSection';
@@ -36,7 +37,8 @@
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { API_SERVICES } from '@/config/constant';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
type Props = {
@@ -49,7 +51,7 @@
const { t } = useTranslation();
const { id } = useParams({ from: '/services/detail/$id' });
- const serviceQuery = useQuery(getServiceQueryOptions(id));
+ const serviceQuery = useSuspenseQuery(getServiceQueryOptions(id));
const { data: serviceData, isLoading, refetch } = serviceQuery;
const form = useForm({
@@ -67,7 +69,8 @@
}, [serviceData, form, isLoading]);
const putService = useMutation({
- mutationFn: putServiceReq,
+ mutationFn: (d: APISIXType['Service']) =>
+ putServiceReq(req, pipeProduce()(d)),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('services.singular') }),
@@ -84,11 +87,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) => {
- putService.mutateAsync(pipeProduce()(d));
- })}
- >
+ <form onSubmit={form.handleSubmit((d) => putService.mutateAsync(d))}>
<FormSectionGeneral />
<FormPartService />
{!readOnly && (
diff --git a/src/routes/services/index.tsx b/src/routes/services/index.tsx
index b01b776..10fa740 100644
--- a/src/routes/services/index.tsx
+++ b/src/routes/services/index.tsx
@@ -16,12 +16,11 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
-import { useEffect, useMemo } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { getServiceListQueryOptions } from '@/apis/services';
+import { getServiceListQueryOptions, useServiceList } from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn,ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
@@ -30,23 +29,11 @@
import { queryClient } from '@/config/global';
import type { APISIXType } from '@/types/schema/apisix';
import { pageSearchSchema } from '@/types/schema/pageSearch';
-import { usePagination } from '@/utils/usePagination';
const ServiceList = () => {
- const { pagination, handlePageChange, updateTotal } = usePagination({
- queryKey: 'services',
- });
-
- const query = useSuspenseQuery(getServiceListQueryOptions(pagination));
- const { data, isLoading, refetch } = query;
+ const { data, isLoading, refetch, pagination } = useServiceList();
const { t } = useTranslation();
- useEffect(() => {
- if (data?.total) {
- updateTotal(data.total);
- }
- }, [data?.total, updateTotal]);
-
const columns = useMemo<ProColumns<APISIXType['RespServiceItem']>[]>(() => {
return [
{
@@ -110,13 +97,7 @@
loading={isLoading}
search={false}
options={false}
- pagination={{
- current: pagination.page,
- pageSize: pagination.pageSize,
- total: pagination.total,
- showSizeChanger: true,
- onChange: handlePageChange,
- }}
+ pagination={pagination}
cardProps={{ bodyStyle: { padding: 0 } }}
toolbar={{
menu: {
diff --git a/src/routes/ssls/add.tsx b/src/routes/ssls/add.tsx
index fe84f82..356f250 100644
--- a/src/routes/ssls/add.tsx
+++ b/src/routes/ssls/add.tsx
@@ -21,6 +21,7 @@
import { FormProvider, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
+import { postSSLReq } from '@/apis/ssls';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartSSL } from '@/components/form-slice/FormPartSSL';
import {
@@ -29,17 +30,14 @@
} from '@/components/form-slice/FormPartSSL/schema';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import PageHeader from '@/components/page/PageHeader';
-import { API_SSLS } from '@/config/constant';
import { req } from '@/config/req';
-import { type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
const SSLAddForm = () => {
const { t } = useTranslation();
const router = useRouter();
const postSSL = useMutation({
- mutationFn: (data: SSLPostType) =>
- req.post<unknown, APISIXType['RespSSLDetail']>(API_SSLS, data),
+ mutationFn: (d: SSLPostType) => postSSLReq(req, pipeProduce()(d)),
async onSuccess() {
notifications.show({
message: t('info.add.success', { name: t('ssls.singular') }),
@@ -59,11 +57,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) =>
- postSSL.mutateAsync(pipeProduce()(d))
- )}
- >
+ <form onSubmit={form.handleSubmit((d) => postSSL.mutateAsync(d))}>
<FormPartSSL />
<FormSubmitBtn>{t('form.btn.add')}</FormSubmitBtn>
</form>
diff --git a/src/routes/ssls/detail.$id.tsx b/src/routes/ssls/detail.$id.tsx
index 4c32313..729585e 100644
--- a/src/routes/ssls/detail.$id.tsx
+++ b/src/routes/ssls/detail.$id.tsx
@@ -28,18 +28,21 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import { getSSLDetailQueryOptions, putSSLReq } from '@/apis/ssls';
+import { getSSLQueryOptions } from '@/apis/hooks';
+import { putSSLReq } from '@/apis/ssls';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartSSL } from '@/components/form-slice/FormPartSSL';
import {
produceToSSLForm,
SSLPutSchema,
+ type SSLPutType,
} from '@/components/form-slice/FormPartSSL/schema';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import { FormSectionGeneral } from '@/components/form-slice/FormSectionGeneral';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { API_SSLS } from '@/config/constant';
+import { req } from '@/config/req';
import { pipeProduce } from '@/utils/producer';
type Props = {
@@ -54,7 +57,7 @@
data: { value: sslData },
isLoading,
refetch,
- } = useSuspenseQuery(getSSLDetailQueryOptions(id));
+ } = useSuspenseQuery(getSSLQueryOptions(id));
const form = useForm({
resolver: zodResolver(SSLPutSchema),
@@ -64,7 +67,7 @@
});
const putSSL = useMutation({
- mutationFn: putSSLReq,
+ mutationFn: (d: SSLPutType) => putSSLReq(req, pipeProduce()(d)),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('ssls.singular') }),
diff --git a/src/routes/ssls/index.tsx b/src/routes/ssls/index.tsx
index 1b48513..9bc31f2 100644
--- a/src/routes/ssls/index.tsx
+++ b/src/routes/ssls/index.tsx
@@ -16,12 +16,11 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
-import { useEffect, useMemo } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { getSSLListQueryOptions } from '@/apis/ssls';
+import { getSSLListQueryOptions, useSSLList } from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn, ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
@@ -30,23 +29,10 @@
import { queryClient } from '@/config/global';
import type { APISIXType } from '@/types/schema/apisix';
import { pageSearchSchema } from '@/types/schema/pageSearch';
-import { usePagination } from '@/utils/usePagination';
function RouteComponent() {
const { t } = useTranslation();
-
- const { pagination, handlePageChange, updateTotal } = usePagination({
- queryKey: 'ssls',
- });
-
- const sslsQuery = useSuspenseQuery(getSSLListQueryOptions(pagination));
- const { data, isLoading, refetch } = sslsQuery;
-
- useEffect(() => {
- if (data?.total) {
- updateTotal(data.total);
- }
- }, [data?.total, updateTotal]);
+ const { data, isLoading, refetch, pagination } = useSSLList();
const columns = useMemo<ProColumns<APISIXType['RespSSLItem']>[]>(() => {
return [
@@ -113,13 +99,7 @@
loading={isLoading}
search={false}
options={false}
- pagination={{
- current: pagination.page,
- pageSize: pagination.pageSize,
- total: pagination.total,
- showSizeChanger: true,
- onChange: handlePageChange,
- }}
+ pagination={pagination}
cardProps={{ bodyStyle: { padding: 0 } }}
toolbar={{
menu: {
diff --git a/src/routes/stream_routes/add.tsx b/src/routes/stream_routes/add.tsx
index 0e986a9..405ad9d 100644
--- a/src/routes/stream_routes/add.tsx
+++ b/src/routes/stream_routes/add.tsx
@@ -24,9 +24,13 @@
import { postStreamRouteReq } from '@/apis/stream_routes';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartStreamRoute } from '@/components/form-slice/FormPartStreamRoute';
-import { StreamRoutePostSchema } from '@/components/form-slice/FormPartStreamRoute/schema';
+import {
+ StreamRoutePostSchema,
+ type StreamRoutePostType,
+} from '@/components/form-slice/FormPartStreamRoute/schema';
import { FormTOCBox } from '@/components/form-slice/FormSection';
import PageHeader from '@/components/page/PageHeader';
+import { req } from '@/config/req';
import { pipeProduce } from '@/utils/producer';
const StreamRouteAddForm = () => {
@@ -34,7 +38,8 @@
const router = useRouter();
const postStreamRoute = useMutation({
- mutationFn: postStreamRouteReq,
+ mutationFn: (d: StreamRoutePostType) =>
+ postStreamRouteReq(req, pipeProduce()(d)),
async onSuccess() {
notifications.show({
message: t('info.add.success', { name: t('streamRoutes.singular') }),
@@ -53,11 +58,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) =>
- postStreamRoute.mutateAsync(pipeProduce()(d))
- )}
- >
+ <form onSubmit={form.handleSubmit((d) => postStreamRoute.mutateAsync(d))}>
<FormPartStreamRoute />
<FormSubmitBtn>{t('form.btn.add')}</FormSubmitBtn>
</form>
diff --git a/src/routes/stream_routes/detail.$id.tsx b/src/routes/stream_routes/detail.$id.tsx
index 4b63485..cb1e8d1 100644
--- a/src/routes/stream_routes/detail.$id.tsx
+++ b/src/routes/stream_routes/detail.$id.tsx
@@ -28,10 +28,8 @@
import { useTranslation } from 'react-i18next';
import { useBoolean } from 'react-use';
-import {
- getStreamRouteQueryOptions,
- putStreamRouteReq,
-} from '@/apis/stream_routes';
+import { getStreamRouteQueryOptions } from '@/apis/hooks';
+import { putStreamRouteReq } from '@/apis/stream_routes';
import { FormSubmitBtn } from '@/components/form/Btn';
import { FormPartStreamRoute } from '@/components/form-slice/FormPartStreamRoute';
import { FormTOCBox } from '@/components/form-slice/FormSection';
@@ -39,7 +37,8 @@
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { API_STREAM_ROUTES } from '@/config/constant';
-import { APISIX } from '@/types/schema/apisix';
+import { req } from '@/config/req';
+import { APISIX, type APISIXType } from '@/types/schema/apisix';
import { pipeProduce } from '@/utils/producer';
type Props = {
@@ -70,7 +69,8 @@
}, [streamRouteData, form, isLoading]);
const putStreamRoute = useMutation({
- mutationFn: putStreamRouteReq,
+ mutationFn: (d: APISIXType['StreamRoute']) =>
+ putStreamRouteReq(req, pipeProduce()(d)),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('streamRoutes.singular') }),
@@ -87,11 +87,7 @@
return (
<FormProvider {...form}>
- <form
- onSubmit={form.handleSubmit((d) => {
- putStreamRoute.mutateAsync(pipeProduce()(d));
- })}
- >
+ <form onSubmit={form.handleSubmit((d) => putStreamRoute.mutateAsync(d))}>
<FormSectionGeneral />
<FormPartStreamRoute />
{!readOnly && (
diff --git a/src/routes/stream_routes/index.tsx b/src/routes/stream_routes/index.tsx
index b7b5dd5..6676af7 100644
--- a/src/routes/stream_routes/index.tsx
+++ b/src/routes/stream_routes/index.tsx
@@ -16,12 +16,11 @@
*/
import type { ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
-import { useSuspenseQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
-import { useEffect, useMemo } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { getStreamRouteListQueryOptions } from '@/apis/stream_routes';
+import { getStreamRouteListQueryOptions, useStreamRouteList } from '@/apis/hooks';
import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
import PageHeader from '@/components/page/PageHeader';
import { ToAddPageBtn,ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
@@ -30,23 +29,11 @@
import { queryClient } from '@/config/global';
import type { APISIXType } from '@/types/schema/apisix';
import { pageSearchSchema } from '@/types/schema/pageSearch';
-import { usePagination } from '@/utils/usePagination';
const StreamRouteList = () => {
- const { pagination, handlePageChange, updateTotal } = usePagination({
- queryKey: 'stream_routes',
- });
-
- const query = useSuspenseQuery(getStreamRouteListQueryOptions(pagination));
- const { data, isLoading, refetch } = query;
+ const { data, isLoading, refetch, pagination } = useStreamRouteList();
const { t } = useTranslation();
- useEffect(() => {
- if (data?.total) {
- updateTotal(data.total);
- }
- }, [data?.total, updateTotal]);
-
const columns = useMemo<
ProColumns<APISIXType['RespStreamRouteItem']>[]
>(() => {
@@ -101,13 +88,7 @@
loading={isLoading}
search={false}
options={false}
- pagination={{
- current: pagination.page,
- pageSize: pagination.pageSize,
- total: pagination.total,
- showSizeChanger: true,
- onChange: handlePageChange,
- }}
+ pagination={pagination}
cardProps={{ bodyStyle: { padding: 0 } }}
toolbar={{
menu: {
diff --git a/src/routes/upstreams/add.tsx b/src/routes/upstreams/add.tsx
index 2445040..a080b81 100644
--- a/src/routes/upstreams/add.tsx
+++ b/src/routes/upstreams/add.tsx
@@ -41,7 +41,7 @@
const { t } = useTranslation();
const router = useRouter();
const postUpstream = useMutation({
- mutationFn: (data: PostUpstreamType) => postUpstreamReq(req, data),
+ mutationFn: (d: PostUpstreamType) => postUpstreamReq(req, d),
async onSuccess(data) {
notifications.show({
message: t('info.add.success', { name: t('upstreams.singular') }),
diff --git a/src/routes/upstreams/detail.$id.tsx b/src/routes/upstreams/detail.$id.tsx
index 7d8e539..441826d 100644
--- a/src/routes/upstreams/detail.$id.tsx
+++ b/src/routes/upstreams/detail.$id.tsx
@@ -76,7 +76,7 @@
});
const putUpstream = useMutation({
- mutationFn: (data: APISIXType['Upstream']) => putUpstreamReq(req, data),
+ mutationFn: (d: APISIXType['Upstream']) => putUpstreamReq(req, d),
async onSuccess() {
notifications.show({
message: t('info.edit.success', { name: t('upstreams.singular') }),
diff --git a/src/types/schema/pageSearch.ts b/src/types/schema/pageSearch.ts
index dc2f25b..fb66356 100644
--- a/src/types/schema/pageSearch.ts
+++ b/src/types/schema/pageSearch.ts
@@ -16,39 +16,22 @@
*/
import { z } from 'zod';
-/**
- * To deprecate pageSize without modifying existing code, use preprocessing.
- */
-export const pageSearchSchema = z.preprocess(
- (data) => {
- // If pageSize is provided but page_size isn't, use pageSize value for page_size
- const inputData = data as Record<string, unknown>;
- if (inputData?.pageSize && inputData?.page_size === undefined) {
- return { ...inputData, page_size: inputData.pageSize };
- }
- return data;
- },
- z
- .object({
- page: z
- .union([z.string(), z.number()])
- .optional()
- .default(1)
- .transform((val) => (val ? Number(val) : 1)),
- pageSize: z
- .union([z.string(), z.number()])
- .optional()
- .default(10)
- .transform((val) => (val ? Number(val) : 10)),
- page_size: z
- .union([z.string(), z.number()])
- .optional()
- .default(10)
- .transform((val) => (val ? Number(val) : 10)),
- name: z.string().optional(),
- label: z.string().optional(),
- })
- .passthrough()
-);
+
+export const pageSearchSchema = z
+ .object({
+ page: z
+ .union([z.string(), z.number()])
+ .optional()
+ .default(1)
+ .transform((val) => (val ? Number(val) : 1)),
+ page_size: z
+ .union([z.string(), z.number()])
+ .optional()
+ .default(10)
+ .transform((val) => (val ? Number(val) : 10)),
+ name: z.string().optional(),
+ label: z.string().optional(),
+ })
+ .passthrough();
export type PageSearchType = z.infer<typeof pageSearchSchema>;
diff --git a/src/utils/usePagination.ts b/src/utils/usePagination.ts
deleted file mode 100644
index d30bfd0..0000000
--- a/src/utils/usePagination.ts
+++ /dev/null
@@ -1,174 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { useRouter } from '@tanstack/react-router';
-import { useCallback, useEffect,useState } from 'react';
-
-import { queryClient } from '@/config/global';
-import type { PageSearchType } from '@/types/schema/pageSearch';
-
-type PaginationState = PageSearchType & {
- total: number;
-};
-
-interface UsePaginationOptions {
- initialPage?: number;
- initialPageSize?: number;
- initialTotal?: number;
- queryKey: string;
- /** If true, updates URL with pagination state */
- syncWithUrl?: boolean;
-}
-
-export interface UsePaginationResult {
- pagination: PaginationState;
- setPagination: React.Dispatch<React.SetStateAction<PaginationState>>;
- handlePageChange: (page: number, pageSize: number) => void;
- createQueryKey: (page: number, pageSize: number) => (string | number)[];
- refreshData: () => void;
- updateTotal: (total: number) => void;
-}
-
-/**
- * Custom hook for managing pagination state and related operations
- *
- * @param options - Configuration options for pagination
- * @returns Pagination state and handlers
- */
-export function usePagination(
- options: UsePaginationOptions
-): UsePaginationResult {
- const {
- initialPage = 1,
- initialPageSize = 10,
- initialTotal = 0,
- queryKey,
- syncWithUrl = true,
- } = options;
-
- // Get router for URL integration
- const router = useRouter();
- const routeSearch = router.state.location.search;
-
- // Initialize pagination from URL if available
- const urlPage =
- syncWithUrl && routeSearch.page
- ? Number(routeSearch.page) || initialPage
- : initialPage;
- const urlPageSize =
- syncWithUrl && routeSearch.pageSize
- ? Number(routeSearch.pageSize) || initialPageSize
- : initialPageSize;
-
- const [pagination, setPagination] = useState<PaginationState>({
- page: urlPage,
- page_size: urlPageSize,
- pageSize: urlPageSize,
- total: initialTotal,
- });
-
- // Sync URL with state when URL params change
- useEffect(() => {
- if (syncWithUrl) {
- const urlPage = routeSearch.page ? Number(routeSearch.page) || 1 : null;
- const urlPageSize = routeSearch.pageSize
- ? Number(routeSearch.pageSize) || 10
- : null;
-
- if (
- (urlPage !== null && urlPage !== pagination.page) ||
- (urlPageSize !== null && urlPageSize !== pagination.pageSize)
- ) {
- setPagination((prev) => ({
- ...prev,
- current: urlPage || prev.page,
- pageSize: urlPageSize || prev.pageSize,
- }));
- }
- }
- }, [routeSearch, syncWithUrl, pagination]);
-
- /**
- * Creates a query key array for React Query based on the given page and pageSize
- */
- const createQueryKey = useCallback(
- (page: number, pageSize: number): (string | number)[] => [
- queryKey,
- page,
- pageSize,
- ],
- [queryKey]
- );
-
- /**
- * Handles page and page size changes
- */
- const handlePageChange = useCallback(
- (page: number, pageSize: number) => {
- setPagination((prev) => ({
- ...prev,
- current: page,
- pageSize: pageSize,
- }));
-
- // Update URL with new pagination state if enabled
- if (syncWithUrl) {
- router.navigate({
- search: (prev) => {
- // Keep all existing search params
- const newSearch = { ...prev };
- newSearch.page = page;
- newSearch.pageSize = pageSize;
- return newSearch as never;
- },
- replace: true,
- });
- }
-
- // Invalidate the query to trigger a refetch with new pagination
- queryClient.invalidateQueries({
- queryKey: createQueryKey(page, pageSize),
- });
- },
- [createQueryKey, router, syncWithUrl]
- );
-
- /**
- * Updates pagination total when data changes
- */
- const updateTotal = useCallback((total: number) => {
- setPagination((prev) => ({ ...prev, total }));
- }, []);
-
- /**
- * Refreshes current page data
- */
- const refreshData = useCallback(() => {
- const { page, pageSize } = pagination;
- queryClient.invalidateQueries({
- queryKey: createQueryKey(page, pageSize),
- });
- }, [createQueryKey, pagination]);
-
- return {
- pagination,
- setPagination,
- handlePageChange,
- createQueryKey,
- refreshData,
- updateTotal,
- };
-}
diff --git a/src/utils/useSearchParams.ts b/src/utils/useSearchParams.ts
index 35fc831..a9c3b3c 100644
--- a/src/utils/useSearchParams.ts
+++ b/src/utils/useSearchParams.ts
@@ -22,21 +22,22 @@
} from '@tanstack/react-router';
import { useCallback } from 'react';
-import type { PageSearchType } from '@/types/schema/pageSearch';
-type RouteTreeIds = RouteIds<RegisteredRouter['routeTree']>;
-export const useSearchParams = <T extends RouteTreeIds>(routeId: T) => {
+export type RouteTreeIds = RouteIds<RegisteredRouter['routeTree']>;
+
+export const useSearchParams = <T extends RouteTreeIds, P extends object>(
+ routeId: T
+) => {
const { useSearch } = getRouteApi<T>(routeId);
const navigate = useNavigate();
- const params = useSearch();
- type Params = typeof params;
+ const params = useSearch() as P;
const setParams = useCallback(
- (props: Partial<Params>) => {
+ (props: Partial<P>) => {
return navigate({
to: '.',
- search: (prev: object) => ({ ...prev, ...props }),
+ search: (prev) => ({ ...prev, ...props }),
});
},
[navigate]
@@ -46,9 +47,10 @@
[navigate]
);
- return { params: params as PageSearchType, setParams, resetParams } as const;
+ return { params, setParams, resetParams } as const;
};
-export type UseSearchParams<T extends RouteTreeIds> = ReturnType<
- typeof useSearchParams<T>
->;
+export type UseSearchParams<
+ T extends RouteTreeIds,
+ P extends object
+> = ReturnType<typeof useSearchParams<T, P>>;
diff --git a/src/utils/useTablePagination.ts b/src/utils/useTablePagination.ts
index 602a510..a1e376a 100644
--- a/src/utils/useTablePagination.ts
+++ b/src/utils/useTablePagination.ts
@@ -20,18 +20,23 @@
import type { FileRoutesByTo } from '@/routeTree.gen';
import type { APISIXListResponse } from '@/types/schema/apisix/type';
-import { pageSearchSchema } from '@/types/schema/pageSearch';
+import {
+ pageSearchSchema,
+ type PageSearchType,
+} from '@/types/schema/pageSearch';
import type { UseSearchParams } from './useSearchParams';
-type ListPageKeys = `${keyof FilterKeys<FileRoutesByTo, 's'>}/`;
-type Props<T> = {
+export type ListPageKeys = `${keyof FilterKeys<FileRoutesByTo, 's'>}/`;
+type Props<T, P extends PageSearchType> = {
data: APISIXListResponse<T>;
/** if params is from useSearchParams, refetch is not needed */
refetch?: () => void;
-} & Pick<UseSearchParams<ListPageKeys>, 'params' | 'setParams'>;
+} & Pick<UseSearchParams<ListPageKeys, P>, 'params' | 'setParams'>;
-export const useTablePagination = <T>(props: Props<T>) => {
+export const useTablePagination = <T, P extends PageSearchType>(
+ props: Props<T, P>
+) => {
const { data, refetch, setParams } = props;
const params = useMemo(
() => pageSearchSchema.parse(props.params),
@@ -40,8 +45,8 @@
const { page, page_size } = params;
const onChange: TablePaginationConfig['onChange'] = useCallback(
- (page: number, pageSize: number) => {
- setParams({ page, page_size: pageSize });
+ (page: number, page_size: number) => {
+ setParams({ page, page_size } as P);
refetch?.();
},
[refetch, setParams]