| @@ -26,15 +26,34 @@ | ||
| 26 | 26 | .column-cb { |
| 27 | 27 | width: 2.2em; |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | + /* NOTE: render_tab_content() in includes/class-metasync-redirections-admin.php always | |
| 31 | + renders both the Redirections and 404 Monitor tab markup into the page (JS just | |
| 32 | + toggles which one is visible), so this view's <style> block and | |
| 33 | + views/metasync-404-monitor.php's both land in the DOM together. Keep their | |
| 34 | + .check-column rules identical, or whichever one is later in source order silently | |
| 35 | + wins the cascade and undoes the other's fix. */ | |
| 30 | 36 | .wrap .wp-list-table th.check-column, |
| 31 | 37 | .wrap .wp-list-table td.check-column { |
| 32 | 38 | width: 2.2em; |
| 33 | - padding: 8px 0 0 3px; | |
| 39 | + } | |
| 40 | + | |
| 41 | + /* Header/footer checkbox cell only ever holds a single-line label, so centring it works. */ | |
| 42 | + .wrap .wp-list-table td.check-column { | |
| 43 | + padding: 0 0 0 3px; | |
| 34 | 44 | vertical-align: middle; |
| 35 | 45 | } |
| 36 | 46 | |
| 47 | + /* Row checkbox cells sit next to columns that can wrap onto multiple lines (e.g. "From" | |
| 48 | + plus its pattern-type badge). Centring against the whole (taller) row pushes the | |
| 49 | + checkbox below the first line of text, so align it to the top like the other columns | |
| 50 | + and nudge it down just enough to sit level with that first line instead. */ | |
| 51 | + .wrap .wp-list-table th.check-column { | |
| 52 | + padding: 9px 0 0 3px; | |
| 53 | + vertical-align: top; | |
| 54 | + } | |
| 55 | + | |
| 37 | 56 | .wrap .wp-list-table th.check-column input[type="checkbox"], |
| 38 | 57 | .wrap .wp-list-table td.check-column input[type="checkbox"] { |
| 39 | 58 | margin: 0; |
| 40 | 59 | padding: 0; |
| @@ -40,8 +59,16 @@ | ||
| 40 | 59 | padding: 0; |
| 41 | 60 | vertical-align: middle; |
| 42 | 61 | } |
| 43 | 62 | |
| 63 | + /* The header/footer cell's row height is computed from the sortable column links' | |
| 64 | + padding and rounds ~1px taller than the checkbox's own box, so vertical-align: | |
| 65 | + middle alone still lands it a hair below the column label text. Nudge it up to | |
| 66 | + sit pixel-level centred (measured against "From" in a real browser). */ | |
| 67 | + .wrap .wp-list-table td.check-column input[type="checkbox"] { | |
| 68 | + transform: translateY(-1px); | |
| 69 | + } | |
| 70 | + | |
| 44 | 71 | .column-sources_from { |
| 45 | 72 | width: 25%; |
| 46 | 73 | } |
| 47 | 74 | |
| @@ -193,10 +220,10 @@ | ||
| 193 | 220 | } |
| 194 | 221 | |
| 195 | 222 | /* Specific button targeting */ |
| 196 | 223 | .wrap input[type="submit"]#doaction, |
| 197 | - .wrap input[type="submit"]#post-query-submit, | |
| 198 | - .wrap input[type="submit"]#search-submit, | |
| 224 | + .wrap input[type="submit"]#redirections-filter-submit, | |
| 225 | + .wrap input[type="submit"]#redirections-search-submit, | |
| 199 | 226 | .wrap input[type="submit"].button { |
| 200 | 227 | background: var(--dashboard-accent) !important; |
| 201 | 228 | border-color: var(--dashboard-accent) !important; |
| 202 | 229 | color: white !important; |
| @@ -205,10 +232,10 @@ | ||
| 205 | 232 | transition: all 0.3s ease !important; |
| 206 | 233 | } |
| 207 | 234 | |
| 208 | 235 | .wrap input[type="submit"]#doaction:hover, |
| 209 | - .wrap input[type="submit"]#post-query-submit:hover, | |
| 210 | - .wrap input[type="submit"]#search-submit:hover, | |
| 236 | + .wrap input[type="submit"]#redirections-filter-submit:hover, | |
| 237 | + .wrap input[type="submit"]#redirections-search-submit:hover, | |
| 211 | 238 | .wrap input[type="submit"].button:hover { |
| 212 | 239 | background: var(--dashboard-accent-hover) !important; |
| 213 | 240 | border-color: var(--dashboard-accent-hover) !important; |
| 214 | 241 | transform: translateY(-1px) !important; |
| @@ -830,9 +857,9 @@ | ||
| 830 | 857 | <div style="background: var(--dashboard-card-bg, #1a1f26); border: 1px solid var(--dashboard-border, #374151); border-radius: 8px; padding: 12px 16px; margin: 15px 0; display: flex; align-items: center; gap: 12px;"> |
| 831 | 858 | <form method="post" style="display: flex; align-items: center; gap: 12px; margin: 0;"> |
| 832 | 859 | <?php wp_nonce_field('metasync_external_redirects_toggle', '_metasync_external_nonce'); ?> |
| 833 | 860 | <label style="display: flex; align-items: center; gap: 8px; cursor: pointer; color: var(--dashboard-text-primary, #fff); font-weight: 500;"> |
| 834 | - <input type="checkbox" name="metasync_allow_external_redirects" value="1" <?php checked($allow_external_current, 1); ?> onchange="this.form.submit();" style="width: 16px; height: 16px;"> | |
| 861 | + <input type="checkbox" name="metasync_allow_external_redirects" value="1" <?php checked($allow_external_current, 1); ?> onchange="this.form.submit();" style="width: 16px; height: 16px; margin: 0; flex-shrink: 0;"> | |
| 835 | 862 | Allow External Redirects |
| 836 | 863 | </label> |
| 837 | 864 | <input type="hidden" name="metasync_save_external_redirects" value="1"> |
| 838 | 865 | <?php if ($allow_external_current) : ?> |
| @@ -842,13 +869,40 @@ | ||
| 842 | 869 | <?php endif; ?> |
| 843 | 870 | </form> |
| 844 | 871 | </div> |
| 845 | 872 | |
| 873 | + | |
| 874 | + <!-- Auto-Redirect on Slug Change Setting --> | |
| 875 | + <?php | |
| 876 | + if (isset($_POST['metasync_save_auto_redirect']) && current_user_can('manage_options') && wp_verify_nonce($_POST['_metasync_auto_redirect_nonce'], 'metasync_auto_redirect_toggle')) { | |
| 877 | + $auto_redirect = isset($_POST['metasync_auto_redirect_enabled']) ? 1 : 0; | |
| 878 | + update_option('metasync_auto_redirect_enabled', $auto_redirect, true); | |
| 879 | + echo '<div class="notice notice-success is-dismissible"><p>Auto-redirect setting updated.</p></div>'; | |
| 880 | + } | |
| 881 | + $auto_redirect_current = get_option('metasync_auto_redirect_enabled', 1); | |
| 882 | + ?> | |
| 883 | + <div style="background: var(--dashboard-card-bg, #1a1f26); border: 1px solid var(--dashboard-border, #374151); border-radius: 8px; padding: 12px 16px; margin: 15px 0; display: flex; align-items: center; gap: 12px;"> | |
| 884 | + <form method="post" style="display: flex; align-items: center; gap: 12px; margin: 0;"> | |
| 885 | + <?php wp_nonce_field('metasync_auto_redirect_toggle', '_metasync_auto_redirect_nonce'); ?> | |
| 886 | + <label style="display: flex; align-items: center; gap: 8px; cursor: pointer; color: var(--dashboard-text-primary, #fff); font-weight: 500;"> | |
| 887 | + <input type="checkbox" name="metasync_auto_redirect_enabled" value="1" <?php checked($auto_redirect_current, 1); ?> onchange="this.form.submit();" style="width: 16px; height: 16px; margin: 0; flex-shrink: 0;"> | |
| 888 | + Auto-Redirect on Slug Change | |
| 889 | + </label> | |
| 890 | + <input type="hidden" name="metasync_save_auto_redirect" value="1"> | |
| 891 | + <?php if ($auto_redirect_current) : ?> | |
| 892 | + <span style="color: var(--dashboard-text-secondary, #9ca3af); font-size: 13px;">Redirects are created automatically when a post or page slug changes.</span> | |
| 893 | + <?php else : ?> | |
| 894 | + <span style="color: var(--dashboard-warning, #f59e0b); font-size: 13px;">Auto-redirects are paused. Slug changes will not create redirect rules (useful during migrations or bulk edits).</span> | |
| 895 | + <?php endif; ?> | |
| 896 | + </form> | |
| 897 | + </div> | |
| 898 | + | |
| 846 | 899 | <!-- Forms are NOT created automatically, so you need to wrap the table in one to use features like bulk actions --> |
| 847 | 900 | <form id="redirection-form" method="post" action=""> |
| 848 | 901 | <?php wp_nonce_field('metasync_redirection_form', 'metasync_redirection_nonce'); ?> |
| 849 | 902 | <?php include "metasync-add-redirection.php"; |
| 850 | - $request_data = metasync_sanitize_input_array($_REQUEST); ?> | |
| 903 | + $request_data = metasync_sanitize_input_array($_REQUEST); | |
| 904 | + $list_state = Metasync_Per_Page_Helper::request_state('redirections'); ?> | |
| 851 | 905 | <!-- For plugins, we also need to ensure that the form posts back to our current page --> |
| 852 | 906 | <input type="hidden" name="page" value="<?php echo esc_attr($request_data['page']) ?>" /> |
| 853 | 907 | |
| 854 | 908 | <!-- Search and Filter Controls --> |
| @@ -881,15 +935,15 @@ | ||
| 881 | 935 | <option value="410" <?php selected(isset($_REQUEST['http_code_filter']) ? $_REQUEST['http_code_filter'] : '', '410'); ?>>410 Gone</option> |
| 882 | 936 | <option value="451" <?php selected(isset($_REQUEST['http_code_filter']) ? $_REQUEST['http_code_filter'] : '', '451'); ?>>451 Unavailable</option> |
| 883 | 937 | </select> |
| 884 | 938 | |
| 885 | - <input type="submit" name="filter_action" id="post-query-submit" class="button" value="Filter"> | |
| 939 | + <input type="submit" name="filter_action" id="redirections-filter-submit" class="button" value="Filter"> | |
| 886 | 940 | </div> |
| 887 | 941 | |
| 888 | 942 | <div class="metasync-search-box"> |
| 889 | - <label class="screen-reader-text" for="post-search-input">Search Redirections:</label> | |
| 890 | - <input type="search" id="post-search-input" name="s" value="<?php echo esc_attr(isset($_REQUEST['s']) ? $_REQUEST['s'] : ''); ?>" placeholder="Search redirections..."> | |
| 891 | - <input type="submit" id="search-submit" class="button" value="Search"> | |
| 943 | + <label class="screen-reader-text" for="redirections-search-input">Search Redirections:</label> | |
| 944 | + <input type="search" id="redirections-search-input" name="s_redir" value="<?php echo esc_attr($list_state['s_redir'] ?? ''); ?>" placeholder="Search redirections..."> | |
| 945 | + <input type="submit" name="search_submit" id="redirections-search-submit" class="button" value="Search"> | |
| 892 | 946 | </div> |
| 893 | 947 | </div> |
| 894 | 948 | |
| 895 | 949 | <!-- Now we can render the completed list table --> |