PluginProbe
Tableberg – Simple Gutenberg Table Block / 1.1.5
Tableberg – Simple Gutenberg Table Block v1.1.5
1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.5 1.0.4 1.0.3 1.0.2 1.0.1 trunk 0.0.2 0.2.1 0.3.2 0.3.3 0.4.1 0.5.0 0.5.1 0.5.2 0.5.3 0.5.4 0.5.5 0.5.6 0.5.7 All 42 releases
tableberg / src / dynamic-data / hooks / useDynamicData.ts

useDynamicData.ts in Tableberg – Simple Gutenberg Table Block 1.1.5, at src/dynamic-data/hooks/useDynamicData.ts

154 lines 4.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useCallback } from "react";
2 import { useQuery, useQueryClient } from "@tanstack/react-query";
3 import apiFetch from "@wordpress/api-fetch";
4 import { useSelect } from "@wordpress/data";
5 import { store as editorStore } from "@wordpress/editor";
6 import { BindingSource, ElementBindings } from "../types";
7 import { useTableStore } from "../../store";
8
9 function resolvePostId(
10 binding: BindingSource | undefined,
11 contextPostId?: number
12 ): number | undefined {
13 if (!binding) {
14 return undefined;
15 }
16 return binding.postId ?? contextPostId;
17 }
18
19 async function queryDynamicData(key: string, postId?: number) {
20 const params = new URLSearchParams({ key });
21
22 if (postId) {
23 params.append("postId", postId.toString());
24 }
25
26 const response = await apiFetch<{
27 success: boolean;
28 value: string | null;
29 }>({
30 path: `/tableberg/v1/dynamic-data/preview?${params.toString()}`,
31 });
32
33 return response;
34 }
35
36 export function useDynamicData(
37 binding: BindingSource | undefined,
38 contextPostId?: number
39 ) {
40 const queryClient = useQueryClient();
41 const postId = resolvePostId(binding, contextPostId);
42
43 const query = useQuery({
44 queryKey: ["dynamicData", binding?.key, postId],
45 queryFn: () => (binding ? queryDynamicData(binding.key, postId) : null),
46 enabled: !!binding && !!postId,
47 staleTime: Infinity,
48 });
49
50 const refresh = useCallback(async () => {
51 if (!binding) return;
52 await queryClient.invalidateQueries({
53 queryKey: ["dynamicData", binding.key, postId],
54 });
55 }, [binding, postId, queryClient]);
56
57 return {
58 data: query.data?.value ?? null,
59 isLoading: query.isLoading,
60 isCached: query.data?.value !== null && !query.isFetching,
61 refresh,
62 };
63 }
64
65 export function useDynamicDataBindings(bindings: ElementBindings | undefined) {
66 const queryClient = useQueryClient();
67 const bindingDefinitions = useTableStore(state => state.bindings);
68
69 const currentPostId = useSelect(select => {
70 const editorSelect = select(editorStore) as {
71 getCurrentPostId?: () => number | undefined;
72 };
73 return editorSelect.getCurrentPostId?.() ?? undefined;
74 }, []);
75
76 const resolvedBindings = Object.entries(bindings || {}).reduce<
77 Record<string, BindingSource>
78 >((acc, [path, bindingId]) => {
79 const binding = bindingDefinitions[bindingId];
80 if (binding) {
81 acc[path] = binding;
82 }
83 return acc;
84 }, {});
85
86 const query = useQuery({
87 queryKey: ["dynamicDataBindings", currentPostId, resolvedBindings],
88 queryFn: async () => {
89 if (!bindings) return {};
90 const newValues: Record<string, string | null> = {};
91 await Promise.all(
92 Object.entries(resolvedBindings).map(
93 async ([path, binding]) => {
94 try {
95 const postId = resolvePostId(
96 binding,
97 currentPostId
98 );
99 const response = await queryDynamicData(
100 binding.key,
101 postId
102 );
103 if (response.success) {
104 newValues[path] =
105 response.value ?? binding.fallback ?? null;
106 }
107 } catch {}
108 }
109 )
110 );
111 return newValues;
112 },
113 enabled: Object.keys(resolvedBindings).length > 0 && !!currentPostId,
114 staleTime: Infinity,
115 });
116
117 const refreshAll = useCallback(async () => {
118 if (!bindings) return;
119 await queryClient.invalidateQueries({
120 queryKey: ["dynamicDataBindings", currentPostId, resolvedBindings],
121 });
122 }, [bindings, currentPostId, queryClient, resolvedBindings]);
123
124 return {
125 values: (query.data as Record<string, string | null>) || {},
126 isLoading: query.isLoading,
127 isCached: Object.keys(query.data || {}).length > 0 && !query.isFetching,
128 refreshAll,
129 };
130 }
131
132 export async function fetchAvailableMetaKeys(
133 postId?: number
134 ): Promise<Array<{ key: string; label?: string }>> {
135 const params = new URLSearchParams();
136 if (postId) {
137 params.append("postId", postId.toString());
138 }
139
140 const query = params.toString();
141 const path = `/tableberg/v1/dynamic-data/meta-keys${query ? `?${query}` : ""}`;
142
143 try {
144 const response = await apiFetch<{
145 keys: Array<{ key: string; label?: string }>;
146 }>({ path });
147 return response.keys;
148 } catch {
149 return [];
150 }
151 }
152
153 export { useDynamicData as default };
154