payload-wordpress-migrator 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +586 -0
- package/dist/components/BeforeDashboardClient.d.ts +14 -0
- package/dist/components/BeforeDashboardClient.js +225 -0
- package/dist/components/BeforeDashboardClient.js.map +1 -0
- package/dist/components/BeforeDashboardClient.module.css +175 -0
- package/dist/components/BeforeDashboardServer.d.ts +1 -0
- package/dist/components/BeforeDashboardServer.js +29 -0
- package/dist/components/BeforeDashboardServer.js.map +1 -0
- package/dist/components/ContentTypeSelect.d.ts +4 -0
- package/dist/components/ContentTypeSelect.js +147 -0
- package/dist/components/ContentTypeSelect.js.map +1 -0
- package/dist/components/FieldMappingConfiguration.d.ts +5 -0
- package/dist/components/FieldMappingConfiguration.js +361 -0
- package/dist/components/FieldMappingConfiguration.js.map +1 -0
- package/dist/components/FieldMappingConfiguration.module.css +75 -0
- package/dist/components/MigrationDashboardClient.d.ts +6 -0
- package/dist/components/MigrationDashboardClient.js +49 -0
- package/dist/components/MigrationDashboardClient.js.map +1 -0
- package/dist/components/MigrationDashboardClient.module.css +749 -0
- package/dist/components/SimpleFieldMapping.d.ts +5 -0
- package/dist/components/SimpleFieldMapping.js +437 -0
- package/dist/components/SimpleFieldMapping.js.map +1 -0
- package/dist/components/dashboard/JobActionButtons.d.ts +8 -0
- package/dist/components/dashboard/JobActionButtons.js +91 -0
- package/dist/components/dashboard/JobActionButtons.js.map +1 -0
- package/dist/components/dashboard/JobsTable.d.ts +6 -0
- package/dist/components/dashboard/JobsTable.js +86 -0
- package/dist/components/dashboard/JobsTable.js.map +1 -0
- package/dist/components/dashboard/LogViewer.d.ts +3 -0
- package/dist/components/dashboard/LogViewer.js +35 -0
- package/dist/components/dashboard/LogViewer.js.map +1 -0
- package/dist/components/dashboard/SiteConfigPanel.d.ts +12 -0
- package/dist/components/dashboard/SiteConfigPanel.js +205 -0
- package/dist/components/dashboard/SiteConfigPanel.js.map +1 -0
- package/dist/components/dashboard/StatsOverview.d.ts +5 -0
- package/dist/components/dashboard/StatsOverview.js +72 -0
- package/dist/components/dashboard/StatsOverview.js.map +1 -0
- package/dist/components/dashboard/index.d.ts +7 -0
- package/dist/components/dashboard/index.js +7 -0
- package/dist/components/dashboard/index.js.map +1 -0
- package/dist/components/dashboard/types.d.ts +46 -0
- package/dist/components/dashboard/types.js +2 -0
- package/dist/components/dashboard/types.js.map +1 -0
- package/dist/components/dashboard/useMigrationDashboard.d.ts +15 -0
- package/dist/components/dashboard/useMigrationDashboard.js +584 -0
- package/dist/components/dashboard/useMigrationDashboard.js.map +1 -0
- package/dist/exports/client.d.ts +4 -0
- package/dist/exports/client.js +5 -0
- package/dist/exports/client.js.map +1 -0
- package/dist/exports/rsc.d.ts +1 -0
- package/dist/exports/rsc.js +2 -0
- package/dist/exports/rsc.js.map +1 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.js +443 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/content/blocks.d.ts +6 -0
- package/dist/utils/content/blocks.js +93 -0
- package/dist/utils/content/blocks.js.map +1 -0
- package/dist/utils/content/fieldMapping.d.ts +9 -0
- package/dist/utils/content/fieldMapping.js +218 -0
- package/dist/utils/content/fieldMapping.js.map +1 -0
- package/dist/utils/content/index.d.ts +4 -0
- package/dist/utils/content/index.js +4 -0
- package/dist/utils/content/index.js.map +1 -0
- package/dist/utils/content/transformer.d.ts +5 -0
- package/dist/utils/content/transformer.js +323 -0
- package/dist/utils/content/transformer.js.map +1 -0
- package/dist/utils/endpoints/handlers.d.ts +9 -0
- package/dist/utils/endpoints/handlers.js +201 -0
- package/dist/utils/endpoints/handlers.js.map +1 -0
- package/dist/utils/endpoints/index.d.ts +2 -0
- package/dist/utils/endpoints/index.js +2 -0
- package/dist/utils/endpoints/index.js.map +1 -0
- package/dist/utils/fields/analyzer.d.ts +7 -0
- package/dist/utils/fields/analyzer.js +502 -0
- package/dist/utils/fields/analyzer.js.map +1 -0
- package/dist/utils/fields/index.d.ts +2 -0
- package/dist/utils/fields/index.js +2 -0
- package/dist/utils/fields/index.js.map +1 -0
- package/dist/utils/helpers/auth.d.ts +9 -0
- package/dist/utils/helpers/auth.js +50 -0
- package/dist/utils/helpers/auth.js.map +1 -0
- package/dist/utils/helpers/cache.d.ts +11 -0
- package/dist/utils/helpers/cache.js +47 -0
- package/dist/utils/helpers/cache.js.map +1 -0
- package/dist/utils/helpers/concurrency.d.ts +2 -0
- package/dist/utils/helpers/concurrency.js +26 -0
- package/dist/utils/helpers/concurrency.js.map +1 -0
- package/dist/utils/helpers/index.d.ts +8 -0
- package/dist/utils/helpers/index.js +8 -0
- package/dist/utils/helpers/index.js.map +1 -0
- package/dist/utils/helpers/objectHelpers.d.ts +3 -0
- package/dist/utils/helpers/objectHelpers.js +22 -0
- package/dist/utils/helpers/objectHelpers.js.map +1 -0
- package/dist/utils/helpers/rateLimiter.d.ts +10 -0
- package/dist/utils/helpers/rateLimiter.js +29 -0
- package/dist/utils/helpers/rateLimiter.js.map +1 -0
- package/dist/utils/helpers/responses.d.ts +3 -0
- package/dist/utils/helpers/responses.js +23 -0
- package/dist/utils/helpers/responses.js.map +1 -0
- package/dist/utils/helpers/wpHelpers.d.ts +6 -0
- package/dist/utils/helpers/wpHelpers.js +29 -0
- package/dist/utils/helpers/wpHelpers.js.map +1 -0
- package/dist/utils/lexical/constants.d.ts +37 -0
- package/dist/utils/lexical/constants.js +58 -0
- package/dist/utils/lexical/constants.js.map +1 -0
- package/dist/utils/lexical/htmlParser.d.ts +20 -0
- package/dist/utils/lexical/htmlParser.js +253 -0
- package/dist/utils/lexical/htmlParser.js.map +1 -0
- package/dist/utils/lexical/htmlToLexicalConverter.d.ts +55 -0
- package/dist/utils/lexical/htmlToLexicalConverter.js +999 -0
- package/dist/utils/lexical/htmlToLexicalConverter.js.map +1 -0
- package/dist/utils/lexical/index.d.ts +5 -0
- package/dist/utils/lexical/index.js +4 -0
- package/dist/utils/lexical/index.js.map +1 -0
- package/dist/utils/lexical/nodeFactories.d.ts +21 -0
- package/dist/utils/lexical/nodeFactories.js +91 -0
- package/dist/utils/lexical/nodeFactories.js.map +1 -0
- package/dist/utils/lexical/preprocessor.d.ts +4 -0
- package/dist/utils/lexical/preprocessor.js +302 -0
- package/dist/utils/lexical/preprocessor.js.map +1 -0
- package/dist/utils/media/download.d.ts +7 -0
- package/dist/utils/media/download.js +85 -0
- package/dist/utils/media/download.js.map +1 -0
- package/dist/utils/media/extraction.d.ts +12 -0
- package/dist/utils/media/extraction.js +58 -0
- package/dist/utils/media/extraction.js.map +1 -0
- package/dist/utils/media/import.d.ts +7 -0
- package/dist/utils/media/import.js +146 -0
- package/dist/utils/media/import.js.map +1 -0
- package/dist/utils/media/index.d.ts +6 -0
- package/dist/utils/media/index.js +6 -0
- package/dist/utils/media/index.js.map +1 -0
- package/dist/utils/media/upload.d.ts +4 -0
- package/dist/utils/media/upload.js +46 -0
- package/dist/utils/media/upload.js.map +1 -0
- package/dist/utils/media/validation.d.ts +8 -0
- package/dist/utils/media/validation.js +60 -0
- package/dist/utils/media/validation.js.map +1 -0
- package/dist/utils/migration/index.d.ts +3 -0
- package/dist/utils/migration/index.js +3 -0
- package/dist/utils/migration/index.js.map +1 -0
- package/dist/utils/migration/jobCrud.d.ts +4 -0
- package/dist/utils/migration/jobCrud.js +380 -0
- package/dist/utils/migration/jobCrud.js.map +1 -0
- package/dist/utils/migration/orchestrator.d.ts +5 -0
- package/dist/utils/migration/orchestrator.js +756 -0
- package/dist/utils/migration/orchestrator.js.map +1 -0
- package/dist/utils/types.d.ts +201 -0
- package/dist/utils/types.js +14 -0
- package/dist/utils/types.js.map +1 -0
- package/dist/utils/wordpress/client.d.ts +61 -0
- package/dist/utils/wordpress/client.js +365 -0
- package/dist/utils/wordpress/client.js.map +1 -0
- package/dist/utils/wordpress/index.d.ts +2 -0
- package/dist/utils/wordpress/index.js +2 -0
- package/dist/utils/wordpress/index.js.map +1 -0
- package/dist/utils/wordpressApi.d.ts +11 -0
- package/dist/utils/wordpressApi.js +25 -0
- package/dist/utils/wordpressApi.js.map +1 -0
- package/package.json +155 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useField } from '@payloadcms/ui';
|
|
4
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
5
|
+
import styles from './FieldMappingConfiguration.module.css';
|
|
6
|
+
|
|
7
|
+
const FieldMappingConfiguration = ({ path })=>{
|
|
8
|
+
const { setValue, value } = useField({
|
|
9
|
+
path
|
|
10
|
+
});
|
|
11
|
+
const { value: contentTypeValue } = useField({
|
|
12
|
+
path: 'contentType'
|
|
13
|
+
});
|
|
14
|
+
const { value: targetCollectionValue } = useField({
|
|
15
|
+
path: 'targetCollection'
|
|
16
|
+
});
|
|
17
|
+
const [wpFields, setWpFields] = useState([]);
|
|
18
|
+
const [payloadFields, setPayloadFields] = useState([]);
|
|
19
|
+
const [fieldMappings, setFieldMappings] = useState([]);
|
|
20
|
+
const [loading, setLoading] = useState(false);
|
|
21
|
+
const [error, setError] = useState('');
|
|
22
|
+
// Parse existing field mappings from JSON value
|
|
23
|
+
useEffect(()=>{
|
|
24
|
+
if (value) {
|
|
25
|
+
try {
|
|
26
|
+
const parsed = typeof value === 'string' ? JSON.parse(value) : value;
|
|
27
|
+
if (parsed && Array.isArray(parsed.fieldMappings)) {
|
|
28
|
+
setFieldMappings(parsed.fieldMappings);
|
|
29
|
+
}
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error('Failed to parse existing field mappings:', error);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}, [
|
|
35
|
+
value
|
|
36
|
+
]);
|
|
37
|
+
// Flatten nested fields with dot notation paths
|
|
38
|
+
const flattenFields = (fields, prefix = '')=>{
|
|
39
|
+
const flattened = [];
|
|
40
|
+
fields.forEach((field)=>{
|
|
41
|
+
const fieldPath = prefix ? `${prefix}.${field.name}` : field.name;
|
|
42
|
+
flattened.push({
|
|
43
|
+
...field,
|
|
44
|
+
label: field.label || field.name,
|
|
45
|
+
path: fieldPath
|
|
46
|
+
});
|
|
47
|
+
// Handle nested fields
|
|
48
|
+
if (field.fields && Array.isArray(field.fields)) {
|
|
49
|
+
flattened.push(...flattenFields(field.fields, fieldPath));
|
|
50
|
+
}
|
|
51
|
+
// Handle array fields with nested schemas
|
|
52
|
+
if (field.type === 'array' && field.of && Array.isArray(field.of)) {
|
|
53
|
+
field.of.forEach((arrayField, index)=>{
|
|
54
|
+
if (arrayField.fields) {
|
|
55
|
+
flattened.push(...flattenFields(arrayField.fields, `${fieldPath}[${index}]`));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// Handle group fields
|
|
60
|
+
if (field.type === 'group' && field.fields) {
|
|
61
|
+
flattened.push(...flattenFields(field.fields, fieldPath));
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return flattened;
|
|
65
|
+
};
|
|
66
|
+
// Fetch WordPress content type fields
|
|
67
|
+
const fetchWordPressFields = useCallback(async (contentType)=>{
|
|
68
|
+
try {
|
|
69
|
+
setLoading(true);
|
|
70
|
+
setError('');
|
|
71
|
+
const savedConfig = localStorage.getItem('wp-site-config');
|
|
72
|
+
if (!savedConfig) {
|
|
73
|
+
throw new Error('WordPress site configuration not found');
|
|
74
|
+
}
|
|
75
|
+
const config = JSON.parse(savedConfig);
|
|
76
|
+
const response = await fetch('/api/wordpress/content-fields', {
|
|
77
|
+
body: JSON.stringify({
|
|
78
|
+
contentType,
|
|
79
|
+
wpPassword: config.wpPassword,
|
|
80
|
+
wpSiteUrl: config.wpSiteUrl,
|
|
81
|
+
wpUsername: config.wpUsername
|
|
82
|
+
}),
|
|
83
|
+
headers: {
|
|
84
|
+
'Content-Type': 'application/json'
|
|
85
|
+
},
|
|
86
|
+
method: 'POST'
|
|
87
|
+
});
|
|
88
|
+
const result = await response.json();
|
|
89
|
+
if (response.ok && result.success) {
|
|
90
|
+
const flattened = flattenFields(result.fields || []);
|
|
91
|
+
setWpFields(flattened);
|
|
92
|
+
} else {
|
|
93
|
+
throw new Error(result.error || 'Failed to fetch WordPress fields');
|
|
94
|
+
}
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error('Error fetching WordPress fields:', error);
|
|
97
|
+
setError(error instanceof Error ? error.message : 'Failed to fetch WordPress fields');
|
|
98
|
+
setWpFields([]);
|
|
99
|
+
} finally{
|
|
100
|
+
setLoading(false);
|
|
101
|
+
}
|
|
102
|
+
}, []) // Empty dependency array since the function doesn't depend on any props or state
|
|
103
|
+
;
|
|
104
|
+
// Fetch Payload collection fields
|
|
105
|
+
const fetchPayloadFields = useCallback(async (collectionSlug)=>{
|
|
106
|
+
try {
|
|
107
|
+
const response = await fetch(`/api/collections/${collectionSlug}/fields`);
|
|
108
|
+
const result = await response.json();
|
|
109
|
+
if (response.ok) {
|
|
110
|
+
const flattened = flattenFields(result.fields || []);
|
|
111
|
+
setPayloadFields(flattened);
|
|
112
|
+
} else {
|
|
113
|
+
throw new Error('Failed to fetch Payload collection fields');
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.error('Error fetching Payload fields:', error);
|
|
117
|
+
setPayloadFields([]);
|
|
118
|
+
}
|
|
119
|
+
}, []) // Empty dependency array since the function doesn't depend on any props or state
|
|
120
|
+
;
|
|
121
|
+
// Load fields when both content type and target collection are selected
|
|
122
|
+
useEffect(()=>{
|
|
123
|
+
if (contentTypeValue && targetCollectionValue) {
|
|
124
|
+
void fetchWordPressFields(contentTypeValue);
|
|
125
|
+
void fetchPayloadFields(targetCollectionValue);
|
|
126
|
+
} else {
|
|
127
|
+
setWpFields([]);
|
|
128
|
+
setPayloadFields([]);
|
|
129
|
+
setFieldMappings([]);
|
|
130
|
+
}
|
|
131
|
+
}, [
|
|
132
|
+
contentTypeValue,
|
|
133
|
+
targetCollectionValue,
|
|
134
|
+
fetchWordPressFields,
|
|
135
|
+
fetchPayloadFields
|
|
136
|
+
]);
|
|
137
|
+
// Add new field mapping
|
|
138
|
+
const addFieldMapping = ()=>{
|
|
139
|
+
const newMapping = {
|
|
140
|
+
payloadField: '',
|
|
141
|
+
wpField: ''
|
|
142
|
+
};
|
|
143
|
+
const updatedMappings = [
|
|
144
|
+
...fieldMappings,
|
|
145
|
+
newMapping
|
|
146
|
+
];
|
|
147
|
+
setFieldMappings(updatedMappings);
|
|
148
|
+
updateValue(updatedMappings);
|
|
149
|
+
};
|
|
150
|
+
// Remove field mapping
|
|
151
|
+
const removeFieldMapping = (index)=>{
|
|
152
|
+
const updatedMappings = fieldMappings.filter((_, i)=>i !== index);
|
|
153
|
+
setFieldMappings(updatedMappings);
|
|
154
|
+
updateValue(updatedMappings);
|
|
155
|
+
};
|
|
156
|
+
// Update field mapping
|
|
157
|
+
const updateFieldMapping = (index, field, value)=>{
|
|
158
|
+
const updatedMappings = fieldMappings.map((mapping, i)=>i === index ? {
|
|
159
|
+
...mapping,
|
|
160
|
+
[field]: value
|
|
161
|
+
} : mapping);
|
|
162
|
+
setFieldMappings(updatedMappings);
|
|
163
|
+
updateValue(updatedMappings);
|
|
164
|
+
};
|
|
165
|
+
// Update the form value
|
|
166
|
+
const updateValue = (mappings)=>{
|
|
167
|
+
const mappingConfig = {
|
|
168
|
+
contentType: contentTypeValue,
|
|
169
|
+
fieldMappings: mappings,
|
|
170
|
+
targetCollection: targetCollectionValue
|
|
171
|
+
};
|
|
172
|
+
setValue(JSON.stringify(mappingConfig, null, 2));
|
|
173
|
+
};
|
|
174
|
+
if (!contentTypeValue || !targetCollectionValue) {
|
|
175
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
176
|
+
className: "field-type",
|
|
177
|
+
children: [
|
|
178
|
+
/*#__PURE__*/ jsx("div", {
|
|
179
|
+
className: "field-label",
|
|
180
|
+
children: /*#__PURE__*/ jsx("label", {
|
|
181
|
+
children: "Field Mapping Configuration"
|
|
182
|
+
})
|
|
183
|
+
}),
|
|
184
|
+
/*#__PURE__*/ jsx("div", {
|
|
185
|
+
className: "field-description",
|
|
186
|
+
children: 'Please select both "Content Type to Migrate" and "Target Payload Collection" to configure field mappings.'
|
|
187
|
+
})
|
|
188
|
+
]
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
192
|
+
className: "field-type",
|
|
193
|
+
children: [
|
|
194
|
+
/*#__PURE__*/ jsx("div", {
|
|
195
|
+
className: "field-label",
|
|
196
|
+
children: /*#__PURE__*/ jsx("label", {
|
|
197
|
+
children: "Field Mapping Configuration"
|
|
198
|
+
})
|
|
199
|
+
}),
|
|
200
|
+
loading && /*#__PURE__*/ jsx("div", {
|
|
201
|
+
className: "field-description",
|
|
202
|
+
children: "Loading field schemas..."
|
|
203
|
+
}),
|
|
204
|
+
error && /*#__PURE__*/ jsx("div", {
|
|
205
|
+
className: "field-error",
|
|
206
|
+
children: /*#__PURE__*/ jsx("div", {
|
|
207
|
+
className: "field-error__message",
|
|
208
|
+
children: error
|
|
209
|
+
})
|
|
210
|
+
}),
|
|
211
|
+
!loading && !error && (wpFields.length > 0 || payloadFields.length > 0) && /*#__PURE__*/ jsxs("div", {
|
|
212
|
+
className: styles.fieldMappingContainer,
|
|
213
|
+
children: [
|
|
214
|
+
/*#__PURE__*/ jsx("div", {
|
|
215
|
+
className: styles.fieldMappingHeader,
|
|
216
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
217
|
+
className: styles.fieldMappingColumns,
|
|
218
|
+
children: [
|
|
219
|
+
/*#__PURE__*/ jsxs("div", {
|
|
220
|
+
className: styles.fieldMappingColumn,
|
|
221
|
+
children: [
|
|
222
|
+
/*#__PURE__*/ jsxs("h4", {
|
|
223
|
+
children: [
|
|
224
|
+
"WordPress Fields (",
|
|
225
|
+
String(contentTypeValue || ''),
|
|
226
|
+
")"
|
|
227
|
+
]
|
|
228
|
+
}),
|
|
229
|
+
/*#__PURE__*/ jsx("div", {
|
|
230
|
+
className: styles.fieldList,
|
|
231
|
+
children: wpFields.map((field)=>/*#__PURE__*/ jsxs("div", {
|
|
232
|
+
className: styles.fieldItem,
|
|
233
|
+
children: [
|
|
234
|
+
/*#__PURE__*/ jsx("strong", {
|
|
235
|
+
children: field.path
|
|
236
|
+
}),
|
|
237
|
+
/*#__PURE__*/ jsx("span", {
|
|
238
|
+
className: styles.fieldTypeBadge,
|
|
239
|
+
children: field.type
|
|
240
|
+
})
|
|
241
|
+
]
|
|
242
|
+
}, field.path))
|
|
243
|
+
})
|
|
244
|
+
]
|
|
245
|
+
}),
|
|
246
|
+
/*#__PURE__*/ jsxs("div", {
|
|
247
|
+
className: styles.fieldMappingColumn,
|
|
248
|
+
children: [
|
|
249
|
+
/*#__PURE__*/ jsxs("h4", {
|
|
250
|
+
children: [
|
|
251
|
+
"Payload Fields (",
|
|
252
|
+
String(targetCollectionValue || ''),
|
|
253
|
+
")"
|
|
254
|
+
]
|
|
255
|
+
}),
|
|
256
|
+
/*#__PURE__*/ jsx("div", {
|
|
257
|
+
className: styles.fieldList,
|
|
258
|
+
children: payloadFields.map((field)=>/*#__PURE__*/ jsxs("div", {
|
|
259
|
+
className: styles.fieldItem,
|
|
260
|
+
children: [
|
|
261
|
+
/*#__PURE__*/ jsx("strong", {
|
|
262
|
+
children: field.path
|
|
263
|
+
}),
|
|
264
|
+
/*#__PURE__*/ jsx("span", {
|
|
265
|
+
className: styles.fieldTypeBadge,
|
|
266
|
+
children: field.type
|
|
267
|
+
})
|
|
268
|
+
]
|
|
269
|
+
}, field.path))
|
|
270
|
+
})
|
|
271
|
+
]
|
|
272
|
+
})
|
|
273
|
+
]
|
|
274
|
+
})
|
|
275
|
+
}),
|
|
276
|
+
/*#__PURE__*/ jsxs("div", {
|
|
277
|
+
className: styles.fieldMappingMappings,
|
|
278
|
+
children: [
|
|
279
|
+
/*#__PURE__*/ jsxs("div", {
|
|
280
|
+
className: styles.fieldMappingHeader,
|
|
281
|
+
children: [
|
|
282
|
+
/*#__PURE__*/ jsx("h4", {
|
|
283
|
+
children: "Field Mappings"
|
|
284
|
+
}),
|
|
285
|
+
/*#__PURE__*/ jsx("button", {
|
|
286
|
+
className: "btn btn--style-secondary btn--size-small",
|
|
287
|
+
onClick: addFieldMapping,
|
|
288
|
+
type: "button",
|
|
289
|
+
children: "Add Mapping"
|
|
290
|
+
})
|
|
291
|
+
]
|
|
292
|
+
}),
|
|
293
|
+
fieldMappings.map((mapping, index)=>/*#__PURE__*/ jsxs("div", {
|
|
294
|
+
className: styles.fieldMappingRow,
|
|
295
|
+
children: [
|
|
296
|
+
/*#__PURE__*/ jsxs("select", {
|
|
297
|
+
className: "select",
|
|
298
|
+
onChange: (e)=>updateFieldMapping(index, 'wpField', e.target.value),
|
|
299
|
+
value: mapping.wpField,
|
|
300
|
+
children: [
|
|
301
|
+
/*#__PURE__*/ jsx("option", {
|
|
302
|
+
value: "",
|
|
303
|
+
children: "Select WordPress field..."
|
|
304
|
+
}),
|
|
305
|
+
wpFields.map((field)=>/*#__PURE__*/ jsxs("option", {
|
|
306
|
+
value: field.path,
|
|
307
|
+
children: [
|
|
308
|
+
field.path,
|
|
309
|
+
" (",
|
|
310
|
+
field.type,
|
|
311
|
+
")"
|
|
312
|
+
]
|
|
313
|
+
}, field.path))
|
|
314
|
+
]
|
|
315
|
+
}),
|
|
316
|
+
/*#__PURE__*/ jsx("span", {
|
|
317
|
+
className: styles.fieldMappingArrow,
|
|
318
|
+
children: "→"
|
|
319
|
+
}),
|
|
320
|
+
/*#__PURE__*/ jsxs("select", {
|
|
321
|
+
className: "select",
|
|
322
|
+
onChange: (e)=>updateFieldMapping(index, 'payloadField', e.target.value),
|
|
323
|
+
value: mapping.payloadField,
|
|
324
|
+
children: [
|
|
325
|
+
/*#__PURE__*/ jsx("option", {
|
|
326
|
+
value: "",
|
|
327
|
+
children: "Select Payload field..."
|
|
328
|
+
}),
|
|
329
|
+
payloadFields.map((field)=>/*#__PURE__*/ jsxs("option", {
|
|
330
|
+
value: field.path,
|
|
331
|
+
children: [
|
|
332
|
+
field.path,
|
|
333
|
+
" (",
|
|
334
|
+
field.type,
|
|
335
|
+
")"
|
|
336
|
+
]
|
|
337
|
+
}, field.path))
|
|
338
|
+
]
|
|
339
|
+
}),
|
|
340
|
+
/*#__PURE__*/ jsx("button", {
|
|
341
|
+
className: "btn btn--style-error btn--size-small",
|
|
342
|
+
onClick: ()=>removeFieldMapping(index),
|
|
343
|
+
type: "button",
|
|
344
|
+
children: "Remove"
|
|
345
|
+
})
|
|
346
|
+
]
|
|
347
|
+
}, index)),
|
|
348
|
+
fieldMappings.length === 0 && /*#__PURE__*/ jsx("div", {
|
|
349
|
+
className: styles.fieldDescription,
|
|
350
|
+
children: 'No field mappings configured. Click "Add Mapping" to start mapping fields.'
|
|
351
|
+
})
|
|
352
|
+
]
|
|
353
|
+
})
|
|
354
|
+
]
|
|
355
|
+
})
|
|
356
|
+
]
|
|
357
|
+
});
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
export { FieldMappingConfiguration as default };
|
|
361
|
+
//# sourceMappingURL=FieldMappingConfiguration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldMappingConfiguration.js","sources":["../../src/components/FieldMappingConfiguration.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useState } from 'react'\n\nimport styles from './FieldMappingConfiguration.module.css'\n\ntype WordPressField = {\n label: string\n name: string\n nested?: WordPressField[]\n path: string // Full dot notation path like \"meta.custom_field\"\n type: string\n}\n\ntype PayloadField = {\n label: string\n name: string\n nested?: PayloadField[]\n path: string // Full dot notation path\n type: string\n}\n\ntype FieldMapping = {\n payloadField: string\n wpField: string\n}\n\nconst FieldMappingConfiguration: React.FC<{ path: string }> = ({ path }) => {\n const { setValue, value } = useField({ path })\n const { value: contentTypeValue } = useField({ path: 'contentType' })\n const { value: targetCollectionValue } = useField({ path: 'targetCollection' })\n\n const [wpFields, setWpFields] = useState<WordPressField[]>([])\n const [payloadFields, setPayloadFields] = useState<PayloadField[]>([])\n const [fieldMappings, setFieldMappings] = useState<FieldMapping[]>([])\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState('')\n\n // Parse existing field mappings from JSON value\n useEffect(() => {\n if (value) {\n try {\n const parsed = typeof value === 'string' ? JSON.parse(value) : value\n if (parsed && Array.isArray(parsed.fieldMappings)) {\n setFieldMappings(parsed.fieldMappings)\n }\n } catch (error) {\n console.error('Failed to parse existing field mappings:', error)\n }\n }\n }, [value])\n\n // Flatten nested fields with dot notation paths\n const flattenFields = (fields: any[], prefix = ''): any[] => {\n const flattened: any[] = []\n\n fields.forEach((field) => {\n const fieldPath = prefix ? `${prefix}.${field.name}` : field.name\n\n flattened.push({\n ...field,\n label: field.label || field.name,\n path: fieldPath,\n })\n\n // Handle nested fields\n if (field.fields && Array.isArray(field.fields)) {\n flattened.push(...flattenFields(field.fields, fieldPath))\n }\n\n // Handle array fields with nested schemas\n if (field.type === 'array' && field.of && Array.isArray(field.of)) {\n field.of.forEach((arrayField: any, index: number) => {\n if (arrayField.fields) {\n flattened.push(...flattenFields(arrayField.fields, `${fieldPath}[${index}]`))\n }\n })\n }\n\n // Handle group fields\n if (field.type === 'group' && field.fields) {\n flattened.push(...flattenFields(field.fields, fieldPath))\n }\n })\n\n return flattened\n }\n\n // Fetch WordPress content type fields\n const fetchWordPressFields = useCallback(async (contentType: string) => {\n try {\n setLoading(true)\n setError('')\n\n const savedConfig = localStorage.getItem('wp-site-config')\n if (!savedConfig) {\n throw new Error('WordPress site configuration not found')\n }\n\n const config = JSON.parse(savedConfig)\n\n const response = await fetch('/api/wordpress/content-fields', {\n body: JSON.stringify({\n contentType,\n wpPassword: config.wpPassword,\n wpSiteUrl: config.wpSiteUrl,\n wpUsername: config.wpUsername,\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n const result = await response.json()\n\n if (response.ok && result.success) {\n const flattened = flattenFields(result.fields || [])\n setWpFields(flattened)\n } else {\n throw new Error(result.error || 'Failed to fetch WordPress fields')\n }\n } catch (error) {\n console.error('Error fetching WordPress fields:', error)\n setError(error instanceof Error ? error.message : 'Failed to fetch WordPress fields')\n setWpFields([])\n } finally {\n setLoading(false)\n }\n }, []) // Empty dependency array since the function doesn't depend on any props or state\n\n // Fetch Payload collection fields\n const fetchPayloadFields = useCallback(async (collectionSlug: string) => {\n try {\n const response = await fetch(`/api/collections/${collectionSlug}/fields`)\n const result = await response.json()\n\n if (response.ok) {\n const flattened = flattenFields(result.fields || [])\n setPayloadFields(flattened)\n } else {\n throw new Error('Failed to fetch Payload collection fields')\n }\n } catch (error) {\n console.error('Error fetching Payload fields:', error)\n setPayloadFields([])\n }\n }, []) // Empty dependency array since the function doesn't depend on any props or state\n\n // Load fields when both content type and target collection are selected\n useEffect(() => {\n if (contentTypeValue && targetCollectionValue) {\n void fetchWordPressFields(contentTypeValue as string)\n void fetchPayloadFields(targetCollectionValue as string)\n } else {\n setWpFields([])\n setPayloadFields([])\n setFieldMappings([])\n }\n }, [contentTypeValue, targetCollectionValue, fetchWordPressFields, fetchPayloadFields])\n\n // Add new field mapping\n const addFieldMapping = () => {\n const newMapping: FieldMapping = {\n payloadField: '',\n wpField: '',\n }\n const updatedMappings = [...fieldMappings, newMapping]\n setFieldMappings(updatedMappings)\n updateValue(updatedMappings)\n }\n\n // Remove field mapping\n const removeFieldMapping = (index: number) => {\n const updatedMappings = fieldMappings.filter((_, i) => i !== index)\n setFieldMappings(updatedMappings)\n updateValue(updatedMappings)\n }\n\n // Update field mapping\n const updateFieldMapping = (index: number, field: keyof FieldMapping, value: string) => {\n const updatedMappings = fieldMappings.map((mapping, i) =>\n i === index ? { ...mapping, [field]: value } : mapping,\n )\n setFieldMappings(updatedMappings)\n updateValue(updatedMappings)\n }\n\n // Update the form value\n const updateValue = (mappings: FieldMapping[]) => {\n const mappingConfig = {\n contentType: contentTypeValue,\n fieldMappings: mappings,\n targetCollection: targetCollectionValue,\n }\n setValue(JSON.stringify(mappingConfig, null, 2))\n }\n\n if (!contentTypeValue || !targetCollectionValue) {\n return (\n <div className=\"field-type\">\n <div className=\"field-label\">\n <label>Field Mapping Configuration</label>\n </div>\n <div className=\"field-description\">\n Please select both \"Content Type to Migrate\" and \"Target Payload Collection\" to configure\n field mappings.\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"field-type\">\n <div className=\"field-label\">\n <label>Field Mapping Configuration</label>\n </div>\n\n {loading && <div className=\"field-description\">Loading field schemas...</div>}\n\n {error && (\n <div className=\"field-error\">\n <div className=\"field-error__message\">{error}</div>\n </div>\n )}\n\n {!loading && !error && (wpFields.length > 0 || payloadFields.length > 0) && (\n <div className={styles.fieldMappingContainer}>\n <div className={styles.fieldMappingHeader}>\n <div className={styles.fieldMappingColumns}>\n <div className={styles.fieldMappingColumn}>\n <h4>WordPress Fields ({String(contentTypeValue || '')})</h4>\n <div className={styles.fieldList}>\n {wpFields.map((field) => (\n <div className={styles.fieldItem} key={field.path}>\n <strong>{field.path}</strong>\n <span className={styles.fieldTypeBadge}>{field.type}</span>\n </div>\n ))}\n </div>\n </div>\n\n <div className={styles.fieldMappingColumn}>\n <h4>Payload Fields ({String(targetCollectionValue || '')})</h4>\n <div className={styles.fieldList}>\n {payloadFields.map((field) => (\n <div className={styles.fieldItem} key={field.path}>\n <strong>{field.path}</strong>\n <span className={styles.fieldTypeBadge}>{field.type}</span>\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n\n <div className={styles.fieldMappingMappings}>\n <div className={styles.fieldMappingHeader}>\n <h4>Field Mappings</h4>\n <button\n className=\"btn btn--style-secondary btn--size-small\"\n onClick={addFieldMapping}\n type=\"button\"\n >\n Add Mapping\n </button>\n </div>\n\n {fieldMappings.map((mapping, index) => (\n <div className={styles.fieldMappingRow} key={index}>\n <select\n className=\"select\"\n onChange={(e) => updateFieldMapping(index, 'wpField', e.target.value)}\n value={mapping.wpField}\n >\n <option value=\"\">Select WordPress field...</option>\n {wpFields.map((field) => (\n <option key={field.path} value={field.path}>\n {field.path} ({field.type})\n </option>\n ))}\n </select>\n\n <span className={styles.fieldMappingArrow}>→</span>\n\n <select\n className=\"select\"\n onChange={(e) => updateFieldMapping(index, 'payloadField', e.target.value)}\n value={mapping.payloadField}\n >\n <option value=\"\">Select Payload field...</option>\n {payloadFields.map((field) => (\n <option key={field.path} value={field.path}>\n {field.path} ({field.type})\n </option>\n ))}\n </select>\n\n <button\n className=\"btn btn--style-error btn--size-small\"\n onClick={() => removeFieldMapping(index)}\n type=\"button\"\n >\n Remove\n </button>\n </div>\n ))}\n\n {fieldMappings.length === 0 && (\n <div className={styles.fieldDescription}>\n No field mappings configured. Click \"Add Mapping\" to start mapping fields.\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default FieldMappingConfiguration\n"],"names":["path","setFieldMappings","value","flattened","label","field","contentType","wpPassword","wpSiteUrl","wpUsername","setError","setWpFields","setPayloadFields","contentTypeValue","targetCollectionValue","fetchWordPressFields","fetchPayloadFields","fieldMappings","newMapping","setValue","loading","error","className","String","wpFields","payloadFields","onClick","index"],"mappings":";;;;;;AA4BA;AACE;AAAuCA;AAAK;AAC5C;;AAAmE;AACnE;;AAA6E;AAE7E;AACA;AACA;AACA;AACA;;;AAIE;;AAEI;AACA;AACEC;AACF;AACF;;AAEA;AACF;;AACEC;AAAM;;AAGV;AACE;;;AAKEC;AACE;AACAC;;AAEF;;;AAIED;AACF;;AAGA;AACEE;;AAEIF;AACF;AACF;AACF;;AAGA;AACEA;AACF;AACF;;AAGF;;;;;;;AASI;AACE;AACF;;;;AAMIG;AACAC;AACAC;AACAC;AACF;;;AAGA;;AAEF;;AAIA;AACE;;;AAGA;AACF;AACF;;AAEEC;AACAC;;;AAGF;;;;;;;;;AAUI;;;AAGA;AACF;AACF;;AAEEC;AACF;;;;;AAKA;AACE;AACA;;AAEAD;AACAC;AACAX;AACF;;AACEY;AAAkBC;AAAuBC;AAAsBC;AAAmB;;AAGtF;AACE;;;AAGA;AACA;AAA4BC;AAAeC;AAAW;;;AAGxD;;AAGA;AACE;;;AAGF;;;;AAKoB;AAAY;;;;AAIhC;;AAGA;AACE;;;;AAIA;AACAC;AACF;;AAGE;;;;;AAGM;AAAO;;;;;AAE0B;;;;AAMzC;AAEA;;;;;AAGM;AAAO;;;AAGRC;;AAA8C;;AAE9CC;;AAEG;;AAAuCA;;;AAI1C;AACMC;;;AACEA;AACH;AAAKA;;;AACEA;;;;AACC;AAAmBC;AAA+B;;;;AACjDD;AACFE;AACMF;;;AACMjB;;;AACHiB;AAAmCjB;;;AAFJA;;;;;AAQxCiB;;;;AACC;AAAiBC;AAAoC;;;;AACpDD;AACFG;AACMH;;;AACMjB;;;AACHiB;AAAmCjB;;;AAFJA;;;;;;;;AAU5CiB;;;AACEA;;;AACC;;;;;;AAKH;;;;AAKFL;AACMK;;;;;AAIDpB;;;;AAEiB;;AAChBsB;AAC0BtB;;AACtBG;AAAW;AAAGA;AAAW;;AADfA;;;;AAMXiB;AAAqC;;;;;AAKzCpB;;;;AAEiB;;AAChBuB;AAC0BvB;;AACtBG;AAAW;AAAGA;AAAW;;AADfA;;;;;AAQfqB;;AAED;;;AAjC0CC;;AAwCxCL;AAAoC;;;;;;;;AASvD;;"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
.fieldMappingContainer {
|
|
2
|
+
border: 1px solid var(--theme-elevation-100);
|
|
3
|
+
border-radius: 4px;
|
|
4
|
+
padding: 16px;
|
|
5
|
+
margin-top: 8px;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.fieldMappingColumns {
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-columns: 1fr 1fr;
|
|
11
|
+
gap: 24px;
|
|
12
|
+
margin-bottom: 24px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.fieldMappingColumn h4 {
|
|
16
|
+
margin: 0 0 12px 0;
|
|
17
|
+
padding-bottom: 8px;
|
|
18
|
+
border-bottom: 1px solid var(--theme-elevation-100);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.fieldList {
|
|
22
|
+
max-height: 200px;
|
|
23
|
+
overflow-y: auto;
|
|
24
|
+
border: 1px solid var(--theme-elevation-100);
|
|
25
|
+
border-radius: 4px;
|
|
26
|
+
padding: 8px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.fieldItem {
|
|
30
|
+
display: flex;
|
|
31
|
+
justify-content: space-between;
|
|
32
|
+
align-items: center;
|
|
33
|
+
padding: 4px 8px;
|
|
34
|
+
margin: 2px 0;
|
|
35
|
+
background: var(--theme-elevation-50);
|
|
36
|
+
border-radius: 3px;
|
|
37
|
+
font-size: 13px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.fieldTypeBadge {
|
|
41
|
+
background: var(--theme-elevation-200);
|
|
42
|
+
padding: 2px 6px;
|
|
43
|
+
border-radius: 12px;
|
|
44
|
+
font-size: 11px;
|
|
45
|
+
color: var(--theme-elevation-800);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.fieldMappingHeader {
|
|
49
|
+
display: flex;
|
|
50
|
+
justify-content: space-between;
|
|
51
|
+
align-items: center;
|
|
52
|
+
margin-bottom: 16px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.fieldMappingHeader h4 {
|
|
56
|
+
margin: 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.fieldMappingRow {
|
|
60
|
+
display: grid;
|
|
61
|
+
grid-template-columns: 1fr auto 1fr auto;
|
|
62
|
+
gap: 12px;
|
|
63
|
+
align-items: center;
|
|
64
|
+
margin-bottom: 12px;
|
|
65
|
+
padding: 12px;
|
|
66
|
+
border: 1px solid var(--theme-elevation-100);
|
|
67
|
+
border-radius: 4px;
|
|
68
|
+
background: var(--theme-background);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.fieldMappingArrow {
|
|
72
|
+
font-size: 18px;
|
|
73
|
+
color: var(--theme-elevation-400);
|
|
74
|
+
font-weight: bold;
|
|
75
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MigrationSummary } from './dashboard/types';
|
|
2
|
+
type MigrationDashboardClientProps = {
|
|
3
|
+
summary: MigrationSummary;
|
|
4
|
+
};
|
|
5
|
+
export declare const MigrationDashboardClient: ({ summary: initialSummary, }: MigrationDashboardClientProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { JobsTable } from './dashboard/JobsTable.js';
|
|
4
|
+
import { LogViewer } from './dashboard/LogViewer.js';
|
|
5
|
+
import { SiteConfigPanel } from './dashboard/SiteConfigPanel.js';
|
|
6
|
+
import { StatsOverview } from './dashboard/StatsOverview.js';
|
|
7
|
+
import { useMigrationDashboard } from './dashboard/useMigrationDashboard.js';
|
|
8
|
+
import styles from './MigrationDashboardClient.module.css';
|
|
9
|
+
|
|
10
|
+
const MigrationDashboardClient = ({ summary: initialSummary })=>{
|
|
11
|
+
const { configState, loading, showSiteConfig, siteConfig, summary, handleCancelEdit, handleEditConfig, handleJobAction, handleSaveConfig, handleSiteConfigChange, setShowSiteConfig, getAllLogs } = useMigrationDashboard(initialSummary);
|
|
12
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
13
|
+
className: "gutter--left gutter--right collection-list__wrap",
|
|
14
|
+
children: [
|
|
15
|
+
/*#__PURE__*/ jsx("div", {
|
|
16
|
+
className: styles.migrationDashboardHeader,
|
|
17
|
+
children: /*#__PURE__*/ jsx("h1", {
|
|
18
|
+
children: "WordPress Migration Dashboard"
|
|
19
|
+
})
|
|
20
|
+
}),
|
|
21
|
+
/*#__PURE__*/ jsx(SiteConfigPanel, {
|
|
22
|
+
configState: configState,
|
|
23
|
+
loading: loading,
|
|
24
|
+
onCancel: handleCancelEdit,
|
|
25
|
+
onConfigChange: handleSiteConfigChange,
|
|
26
|
+
onEdit: handleEditConfig,
|
|
27
|
+
onSave: handleSaveConfig,
|
|
28
|
+
onToggle: ()=>setShowSiteConfig(!showSiteConfig),
|
|
29
|
+
showSiteConfig: showSiteConfig,
|
|
30
|
+
siteConfig: siteConfig
|
|
31
|
+
}),
|
|
32
|
+
/*#__PURE__*/ jsx(StatsOverview, {
|
|
33
|
+
siteConfig: siteConfig,
|
|
34
|
+
summary: summary
|
|
35
|
+
}),
|
|
36
|
+
/*#__PURE__*/ jsx(JobsTable, {
|
|
37
|
+
jobs: summary.recentJobs ?? [],
|
|
38
|
+
loading: loading,
|
|
39
|
+
onJobAction: handleJobAction
|
|
40
|
+
}),
|
|
41
|
+
/*#__PURE__*/ jsx(LogViewer, {
|
|
42
|
+
logs: getAllLogs()
|
|
43
|
+
})
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export { MigrationDashboardClient };
|
|
49
|
+
//# sourceMappingURL=MigrationDashboardClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MigrationDashboardClient.js","sources":["../../src/components/MigrationDashboardClient.tsx"],"sourcesContent":["'use client'\n\nimport { JobsTable } from './dashboard/JobsTable'\nimport { LogViewer } from './dashboard/LogViewer'\nimport { SiteConfigPanel } from './dashboard/SiteConfigPanel'\nimport { StatsOverview } from './dashboard/StatsOverview'\nimport type { MigrationSummary } from './dashboard/types'\nimport { useMigrationDashboard } from './dashboard/useMigrationDashboard'\n\nimport styles from './MigrationDashboardClient.module.css'\n\ntype MigrationDashboardClientProps = {\n summary: MigrationSummary\n}\n\nexport const MigrationDashboardClient = ({\n summary: initialSummary,\n}: MigrationDashboardClientProps) => {\n const {\n configState,\n loading,\n showSiteConfig,\n siteConfig,\n summary,\n handleCancelEdit,\n handleEditConfig,\n handleJobAction,\n handleSaveConfig,\n handleSiteConfigChange,\n setShowSiteConfig,\n getAllLogs,\n } = useMigrationDashboard(initialSummary)\n\n return (\n <div className=\"gutter--left gutter--right collection-list__wrap\">\n <div className={styles.migrationDashboardHeader}>\n <h1>WordPress Migration Dashboard</h1>\n </div>\n\n <SiteConfigPanel\n configState={configState}\n loading={loading}\n onCancel={handleCancelEdit}\n onConfigChange={handleSiteConfigChange}\n onEdit={handleEditConfig}\n onSave={handleSaveConfig}\n onToggle={() => setShowSiteConfig(!showSiteConfig)}\n showSiteConfig={showSiteConfig}\n siteConfig={siteConfig}\n />\n\n <StatsOverview siteConfig={siteConfig} summary={summary} />\n\n <JobsTable\n jobs={summary.recentJobs ?? []}\n loading={loading}\n onJobAction={handleJobAction}\n />\n\n <LogViewer logs={getAllLogs()} />\n </div>\n )\n}\n"],"names":["className"],"mappings":";;;;;;;;;;;AAiCE;;;;AAESA;AACH;AAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BZ;;"}
|