PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 1.0.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v1.0.0
2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.10.0 All 48 releases
thinkrank / src / admin / stores / metadata.js

metadata.js in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 1.0.0, at src/admin/stores/metadata.js

214 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Metadata Data Store
3 *
4 * Manages AI-generated metadata for posts and pages
5 *
6 * @package ThinkRank
7 * @since 1.0.0
8 */
9
10 import { createReduxStore } from '@wordpress/data';
11 import apiFetch from '@wordpress/api-fetch';
12
13 // Initial state
14 const DEFAULT_STATE = {
15 metadata: {},
16 isGenerating: {},
17 generationHistory: {},
18 isLoading: false,
19 };
20
21 // Action types
22 const TYPES = {
23 SET_METADATA: 'SET_METADATA',
24 SET_GENERATING: 'SET_GENERATING',
25 SET_LOADING: 'SET_LOADING',
26 ADD_TO_HISTORY: 'ADD_TO_HISTORY',
27 CLEAR_METADATA: 'CLEAR_METADATA',
28 };
29
30 // Reducer
31 const reducer = (state = DEFAULT_STATE, action) => {
32 switch (action.type) {
33 case TYPES.SET_METADATA:
34 return {
35 ...state,
36 metadata: {
37 ...state.metadata,
38 [action.postId]: action.metadata,
39 },
40 };
41
42 case TYPES.SET_GENERATING:
43 return {
44 ...state,
45 isGenerating: {
46 ...state.isGenerating,
47 [action.postId]: action.generating,
48 },
49 };
50
51 case TYPES.SET_LOADING:
52 return {
53 ...state,
54 isLoading: action.loading,
55 };
56
57 case TYPES.ADD_TO_HISTORY:
58 return {
59 ...state,
60 generationHistory: {
61 ...state.generationHistory,
62 [action.postId]: [
63 ...(state.generationHistory[action.postId] || []),
64 action.entry,
65 ],
66 },
67 };
68
69 case TYPES.CLEAR_METADATA:
70 return {
71 ...state,
72 metadata: {
73 ...state.metadata,
74 [action.postId]: null,
75 },
76 };
77
78 default:
79 return state;
80 }
81 };
82
83 // Actions
84 const actions = {
85 setMetadata(postId, metadata) {
86 return {
87 type: TYPES.SET_METADATA,
88 postId,
89 metadata,
90 };
91 },
92
93 setGenerating(postId, generating) {
94 return {
95 type: TYPES.SET_GENERATING,
96 postId,
97 generating,
98 };
99 },
100
101 setLoading(loading) {
102 return {
103 type: TYPES.SET_LOADING,
104 loading,
105 };
106 },
107
108 addToHistory(postId, entry) {
109 return {
110 type: TYPES.ADD_TO_HISTORY,
111 postId,
112 entry,
113 };
114 },
115
116 clearMetadata(postId) {
117 return {
118 type: TYPES.CLEAR_METADATA,
119 postId,
120 };
121 },
122
123 // Async actions (placeholders for Sprint 2)
124 *generateMetadata(postId, options = {}) {
125 yield actions.setGenerating(postId, true);
126
127 try {
128 // This will be implemented in Sprint 2
129 const metadata = {
130 title: 'AI Generated Title',
131 description: 'AI Generated Description',
132 generated_at: new Date().toISOString(),
133 };
134
135 yield actions.setMetadata(postId, metadata);
136 yield actions.addToHistory(postId, {
137 timestamp: Date.now(),
138 action: 'generated',
139 metadata,
140 });
141
142 return metadata;
143
144 } catch (error) {
145 console.error('Failed to generate metadata:', error);
146 throw error;
147 } finally {
148 yield actions.setGenerating(postId, false);
149 }
150 },
151
152 *loadMetadata(postId) {
153 yield actions.setLoading(true);
154
155 try {
156 // This will be implemented in Sprint 2
157 const metadata = yield apiFetch({
158 path: `/thinkrank/v1/metadata/${postId}`,
159 });
160
161 yield actions.setMetadata(postId, metadata);
162 return metadata;
163
164 } catch (error) {
165 console.error('Failed to load metadata:', error);
166 } finally {
167 yield actions.setLoading(false);
168 }
169 },
170 };
171
172 // Selectors
173 const selectors = {
174 getMetadata(state, postId) {
175 return state.metadata[postId] || null;
176 },
177
178 getIsGenerating(state, postId) {
179 return state.isGenerating[postId] || false;
180 },
181
182 getIsLoading(state) {
183 return state.isLoading;
184 },
185
186 getGenerationHistory(state, postId) {
187 return state.generationHistory[postId] || [];
188 },
189
190 // Computed selectors
191 hasMetadata(state, postId) {
192 return !!state.metadata[postId];
193 },
194
195 getMetadataTitle(state, postId) {
196 const metadata = state.metadata[postId];
197 return metadata?.title || '';
198 },
199
200 getMetadataDescription(state, postId) {
201 const metadata = state.metadata[postId];
202 return metadata?.description || '';
203 },
204 };
205
206 // Create and export store
207 const store = createReduxStore('thinkrank/metadata', {
208 reducer,
209 actions,
210 selectors,
211 });
212
213 export default store;
214