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 / components / essential-seo / schema / SchemaGeneration.js

SchemaGeneration.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/components/essential-seo/schema/SchemaGeneration.js

299 lines 13.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Schema Generation Component
3 *
4 * Extracted from SchemaTab.js - handles schema types selection and generation controls
5 *
6 * @package ThinkRank
7 * @since 1.0.0
8 */
9
10 import React from 'react';
11 import { __ } from '@wordpress/i18n';
12 import {
13 Card,
14 CardBody,
15 CardHeader,
16 CheckboxControl,
17 TextControl,
18 TextareaControl,
19 SelectControl,
20 DateTimePicker,
21 Flex,
22 FlexItem,
23 FormTokenField
24 } from '@wordpress/components';
25 import MediaPicker from '../../common/MediaPicker';
26
27 // Import shared schema configuration
28 import {
29 getSupportedSchemaTypes
30 } from '../../../config/schema-settings-config';
31
32 // Site-level schema forms are now in dedicated tabs
33 // No form imports needed here
34
35 /**
36 * Schema Generation Component
37 */
38 const SchemaGeneration = ({
39 settings,
40 onSettingChange,
41 isLoading
42 }) => {
43 const supportedTypes = getSupportedSchemaTypes('site');
44
45 // Clean up enabled types on component mount
46 React.useEffect(() => {
47 const currentEnabledTypes = settings.enabled_schema_types || [];
48 const cleanedTypes = currentEnabledTypes.filter(type => supportedTypes.includes(type));
49
50 // If there are unsupported types, clean them up
51 if (cleanedTypes.length !== currentEnabledTypes.length) {
52 onSettingChange('enabled_schema_types', cleanedTypes);
53 }
54 }, []); // Only run on mount
55 /**
56 * Handle schema type toggle
57 */
58 const handleSchemaTypeToggle = (schemaType, checked) => {
59 const currentTypes = settings.enabled_schema_types || [];
60 let newTypes;
61
62 if (checked) {
63 newTypes = [...currentTypes, schemaType];
64 } else {
65 newTypes = currentTypes.filter(type => type !== schemaType);
66 }
67
68 onSettingChange('enabled_schema_types', newTypes);
69 };
70
71 const allEnabledTypes = settings.enabled_schema_types || [];
72
73 // Filter enabled types to only include site-level schemas
74 const enabledTypes = allEnabledTypes.filter(type => supportedTypes.includes(type));
75
76 return (
77 <div className="tab-content">
78 {/* Workflow Guide */}
79 <Card size="small" className="thinkrank-mb-md">
80 <CardBody>
81 <div style={{
82 padding: '12px',
83 backgroundColor: '#e7f3ff',
84 border: '1px solid #b3d9ff',
85 borderRadius: '4px',
86 marginBottom: '16px'
87 }}>
88 <h4 style={{ margin: '0 0 8px 0', color: '#0073aa' }}>
89 {__('Site-Level Schema Management', 'thinkrank')}
90 </h4>
91 <p style={{ margin: '0 0 12px 0', color: '#0073aa', fontSize: '14px' }}>
92 {__('This section handles site-wide schema markup (Organization, LocalBusiness, Person, WebSite).', 'thinkrank')}
93 </p>
94 <p style={{ margin: '0 0 12px 0', color: '#0073aa', fontSize: '14px' }}>
95 <strong>{__('For post and page schemas:', 'thinkrank')}</strong> {__('Use the ThinkRank metabox when editing individual posts/pages. It provides Article, BlogPosting, TechnicalArticle, Report, and other content-specific schema types with AI-optimized data.', 'thinkrank')}
96 </p>
97 <ol style={{ margin: '0', paddingLeft: '20px', color: '#0073aa', fontSize: '14px' }}>
98 <li>{__('Select site-level schema types below', 'thinkrank')}</li>
99 <li>{__('Configure organization and website data', 'thinkrank')}</li>
100 <li>{__('Generate and deploy site schema', 'thinkrank')}</li>
101 </ol>
102 </div>
103 </CardBody>
104 </Card>
105
106 {/* Schema Types Selection */}
107 <Card size="small">
108 <CardBody>
109 <h4 className="thinkrank-mb-sm">{__('Select Site-Level Schema Types', 'thinkrank')}</h4>
110 <p className="components-base-control__help thinkrank-mb-md">
111 {__('Choose site-wide schema types that apply to your entire website. Content-specific schemas (Article, BlogPosting, etc.) are handled in the post/page metabox.', 'thinkrank')}
112 </p>
113
114 <div className="thinkrank-schema-types-grid" style={{
115 display: 'grid',
116 gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
117 gap: '12px'
118 }}>
119 {supportedTypes.map(schemaType => {
120 const isChecked = enabledTypes.includes(schemaType);
121
122 // Site-level schema type descriptions
123 const descriptions = {
124 'Organization': __('Company or organization information (site-wide)', 'thinkrank'),
125 'LocalBusiness': __('Local business with physical location (site-wide)', 'thinkrank'),
126 'Person': __('Individual person or author information (site-wide)', 'thinkrank'),
127 'WebSite': __('Website-level information and search functionality', 'thinkrank')
128 };
129
130 return (
131 <div key={schemaType} style={{
132 padding: '12px',
133 border: '1px solid #ddd',
134 borderRadius: '4px',
135 backgroundColor: isChecked ? '#f0f8ff' : '#fff'
136 }}>
137 <CheckboxControl
138 label={schemaType}
139 checked={isChecked}
140 onChange={(checked) => handleSchemaTypeToggle(schemaType, checked)}
141 __nextHasNoMarginBottom={true}
142 />
143 <p style={{
144 margin: '4px 0 0 0',
145 fontSize: '12px',
146 color: '#666',
147 lineHeight: '1.4'
148 }}>
149 {descriptions[schemaType] || __('Schema markup for ' + schemaType, 'thinkrank')}
150 </p>
151 </div>
152 );
153 })}
154 </div>
155
156 {enabledTypes.length === 0 && (
157 <div style={{
158 padding: '12px',
159 backgroundColor: '#fff3cd',
160 border: '1px solid #ffeaa7',
161 borderRadius: '4px',
162 marginTop: '16px'
163 }}>
164 <p style={{ margin: 0, color: '#856404' }}>
165 {__('⚠️ No schema types selected. Choose at least one type to generate schema markup.', 'thinkrank')}
166 </p>
167 </div>
168 )}
169
170 {enabledTypes.length > 0 && (
171 <div style={{
172 padding: '12px',
173 backgroundColor: '#d4edda',
174 border: '1px solid #c3e6cb',
175 borderRadius: '4px',
176 marginTop: '16px'
177 }}>
178 <p style={{ margin: 0, color: '#155724' }}>
179 <strong>{__('Selected Types:', 'thinkrank')}</strong> {enabledTypes.join(', ')}
180 </p>
181 <p style={{ margin: '4px 0 0 0', fontSize: '12px', color: '#155724' }}>
182 {__('Configure organization and website data, then generate schema markup.', 'thinkrank')}
183 </p>
184 </div>
185 )}
186 </CardBody>
187 </Card>
188
189 {/* Content Schema Info Panel */}
190 <Card size="small" className="thinkrank-mb-md">
191 <CardBody>
192 <div style={{
193 padding: '16px',
194 backgroundColor: '#f8f9fa',
195 border: '1px solid #dee2e6',
196 borderRadius: '6px',
197 borderLeft: '4px solid #0073aa'
198 }}>
199 <h4 style={{ margin: '0 0 12px 0', color: '#0073aa', fontSize: '16px' }}>
200 📝 {__('Content Schema Types', 'thinkrank')}
201 </h4>
202 <p style={{ margin: '0 0 12px 0', color: '#495057', fontSize: '14px' }}>
203 {__('Looking for Article, BlogPosting, TechnicalArticle, Report, HowTo, or FAQ schemas?', 'thinkrank')}
204 </p>
205 <p style={{ margin: '0 0 12px 0', color: '#495057', fontSize: '14px' }}>
206 <strong>{__('These are available in the ThinkRank metabox', 'thinkrank')}</strong> {__('when editing individual posts and pages. The metabox provides:', 'thinkrank')}
207 </p>
208 <ul style={{ margin: '0 0 12px 20px', color: '#495057', fontSize: '14px' }}>
209 <li>{__('AI-optimized content integration', 'thinkrank')}</li>
210 <li>{__('Post-specific schema generation', 'thinkrank')}</li>
211 <li>{__('Multiple Article types (Article, BlogPosting, TechnicalArticle, NewsArticle, ScholarlyArticle, Report)', 'thinkrank')}</li>
212 <li>{__('Content-specific schemas (HowTo, FAQ, Event)', 'thinkrank')}</li>
213 </ul>
214 <p style={{ margin: '0', color: '#6c757d', fontSize: '13px', fontStyle: 'italic' }}>
215 {__('💡 This separation ensures site-wide schemas are managed globally while content schemas use actual post data and AI optimization.', 'thinkrank')}
216 </p>
217 </div>
218 </CardBody>
219 </Card>
220
221 {/* Dynamic Configuration Panels */}
222 {enabledTypes.length > 0 && (
223 <div className="thinkrank-schema-config-panels" style={{ marginTop: '16px' }}>
224 {enabledTypes.map(schemaType => {
225 const ConfigPanel = getConfigurationPanel(schemaType, settings, onSettingChange);
226 return ConfigPanel ? (
227 <div key={schemaType} style={{ marginBottom: '16px' }}>
228 {ConfigPanel}
229 </div>
230 ) : null;
231 })}
232 </div>
233 )}
234 </div>
235 );
236
237 /**
238 * Get configuration panel for schema type
239 */
240 function getConfigurationPanel(schemaType, settings, onSettingChange) {
241 // Only show configuration panels for supported site-level schema types
242 const supportedSiteTypes = getSupportedSchemaTypes('site');
243 if (!supportedSiteTypes.includes(schemaType)) {
244 return null;
245 }
246
247 switch (schemaType) {
248 case 'Organization':
249 return (
250 <Card size="small" className="thinkrank-mb-md">
251 <CardBody>
252 <p className="components-base-control__help">
253 {__('Organization schema configuration is available in the Organization tab.', 'thinkrank')}
254 </p>
255 </CardBody>
256 </Card>
257 );
258
259 case 'LocalBusiness':
260 return (
261 <Card size="small" className="thinkrank-mb-md">
262 <CardBody>
263 <p className="components-base-control__help">
264 {__('Local Business schema configuration is available in the Local Business tab.', 'thinkrank')}
265 </p>
266 </CardBody>
267 </Card>
268 );
269
270 case 'Person':
271 return (
272 <Card size="small" className="thinkrank-mb-md">
273 <CardBody>
274 <p className="components-base-control__help">
275 {__('Person schema configuration is available in the Person tab.', 'thinkrank')}
276 </p>
277 </CardBody>
278 </Card>
279 );
280
281 case 'WebSite':
282 return (
283 <Card size="small" className="thinkrank-mb-md">
284 <CardBody>
285 <p className="components-base-control__help">
286 {__('WebSite schema uses your site settings automatically. No additional configuration needed.', 'thinkrank')}
287 </p>
288 </CardBody>
289 </Card>
290 );
291
292 default:
293 return null;
294 }
295 }
296 };
297
298 export default SchemaGeneration;
299