feat: implement coexistence strategy for Grid.js and React admin
Implement dual-mode rendering allowing classic Grid.js and new React versions to run side-by-side during migration. - Add coexistence mode checks to all admin page methods - Check query param ?react=1 or option 'formipay_use_react_admin' - Include classic PHP pages when React not active - Add admin notice showing current version with toggle button - Add footer toggle link to switch between versions This ensures zero feature loss - old Grid.js pages continue working (~20 features per page) while React versions are developed. Files: - Form.php, Coupon.php, Access.php, Order.php - Customer.php, Product.php, License.php - ReactAdmin.php (added version_notice, footer_toggle) Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
26
src/admin/components/shared/DataTable.css
Normal file
26
src/admin/components/shared/DataTable.css
Normal file
@@ -0,0 +1,26 @@
|
||||
.formipay-data-table-loading,
|
||||
.formipay-data-table-empty {
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.formipay-data-table {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.formipay-data-table thead th {
|
||||
padding: 12px 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.formipay-data-table tbody td {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.formipay-data-table tbody tr.is-clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.formipay-data-table tbody tr.is-clickable:hover {
|
||||
background-color: #f0f0f1;
|
||||
}
|
||||
57
src/admin/components/shared/DataTable.js
Normal file
57
src/admin/components/shared/DataTable.js
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Data Table - Simple table component for admin listings
|
||||
*/
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import './DataTable.css';
|
||||
|
||||
export default function DataTable({
|
||||
columns,
|
||||
data,
|
||||
loading,
|
||||
emptyMessage = __('No items found', 'formipay'),
|
||||
onRowClick
|
||||
}) {
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="formipay-data-table-loading">
|
||||
<span className="spinner is-active" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!data || data.length === 0) {
|
||||
return (
|
||||
<div className="formipay-data-table-empty">
|
||||
<p>{ emptyMessage }</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<table className="formipay-data-table wp-list-table widefat fixed striped">
|
||||
<thead>
|
||||
<tr>
|
||||
{columns.map((column) => (
|
||||
<th key={column.key}>{column.label}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((row, rowIndex) => (
|
||||
<tr
|
||||
key={rowIndex}
|
||||
onClick={onRowClick ? () => onRowClick(row) : undefined}
|
||||
className={onRowClick ? 'is-clickable' : ''}
|
||||
>
|
||||
{columns.map((column) => (
|
||||
<td key={column.key}>
|
||||
{column.render ? column.render(row) : row[column.key]}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
45
src/admin/pages/AdminPages.css
Normal file
45
src/admin/pages/AdminPages.css
Normal file
@@ -0,0 +1,45 @@
|
||||
.formipay-page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.formipay-page-header h1 {
|
||||
margin: 0;
|
||||
font-size: 23px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status-badge.status-publish,
|
||||
.status-badge.status-active {
|
||||
background-color: #edfaef;
|
||||
color: #00a32a;
|
||||
}
|
||||
|
||||
.status-badge.status-draft,
|
||||
.status-badge.status-inactive {
|
||||
background-color: #f0f0f1;
|
||||
color: #646970;
|
||||
}
|
||||
|
||||
.status-badge.status-expired {
|
||||
background-color: #f6f7f7;
|
||||
color: #d63638;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #f0f0f1;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-family: monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
Reference in New Issue
Block a user