PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.21
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.21
2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 2.5.23 All 138 releases
metasync / views / metasync-redirection.php

metasync-redirection.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.6.21, at views/metasync-redirection.php

928 lines 31.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <style type="text/css">
2 <?php
3 // If this file is called directly, abort.
4 if (!defined('ABSPATH')) {
5 exit;
6 }
7 ?>
8 /* Root Variables - Dashboard Color Scheme */
9 :root {
10 --dashboard-bg: #0f1419;
11 --dashboard-card-bg: #1a1f26;
12 --dashboard-card-hover: #222831;
13 --dashboard-text-primary: #ffffff;
14 --dashboard-text-secondary: #9ca3af;
15 --dashboard-accent: #3b82f6;
16 --dashboard-accent-hover: #2563eb;
17 --dashboard-success: #10b981;
18 --dashboard-warning: #f59e0b;
19 --dashboard-error: #ef4444;
20 --dashboard-border: #374151;
21 --dashboard-gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
22 --dashboard-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.1);
23 --dashboard-shadow-hover: 0 20px 25px -5px rgba(0, 0, 0, 0.4), 0 10px 10px -5px rgba(0, 0, 0, 0.2);
24 }
25
26 .column-cb {
27 width: 2.2em;
28 }
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. */
36 .wrap .wp-list-table th.check-column,
37 .wrap .wp-list-table td.check-column {
38 width: 2.2em;
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;
44 vertical-align: middle;
45 }
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
56 .wrap .wp-list-table th.check-column input[type="checkbox"],
57 .wrap .wp-list-table td.check-column input[type="checkbox"] {
58 margin: 0;
59 padding: 0;
60 vertical-align: middle;
61 }
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
71 .column-sources_from {
72 width: 25%;
73 }
74
75 .column-url_redirect_to {
76 width: 25%;
77 }
78
79 .column-http_code {
80 width: 10%;
81 }
82
83 .column-pattern_type {
84 width: 12%;
85 }
86
87 .column-hits_count {
88 width: 8%;
89 }
90
91 .column-status {
92 width: 10%;
93 }
94
95 .column-last_accessed_at {
96 width: 10%;
97 }
98
99 /* Page background */
100 body {
101 background: var(--dashboard-bg) !important;
102 }
103
104 .wrap {
105 background: var(--dashboard-bg) !important;
106 color: var(--dashboard-text-primary) !important;
107 }
108
109 /* Enhanced table styling with higher specificity */
110 .wrap .wp-list-table {
111 background: var(--dashboard-card-bg) !important;
112 border: 1px solid var(--dashboard-border) !important;
113 border-radius: 12px !important;
114 overflow: hidden !important;
115 box-shadow: var(--dashboard-shadow) !important;
116 }
117
118 .wrap .wp-list-table th {
119 background: var(--dashboard-card-hover) !important;
120 color: var(--dashboard-text-primary) !important;
121 border-bottom: 1px solid var(--dashboard-border) !important;
122 font-weight: 600 !important;
123 }
124
125 .wrap .wp-list-table td {
126 background: var(--dashboard-card-bg) !important;
127 border-bottom: 1px solid var(--dashboard-border) !important;
128 color: var(--dashboard-text-secondary) !important;
129 }
130
131 .wrap .wp-list-table tr:hover td {
132 background: var(--dashboard-card-hover) !important;
133 color: var(--dashboard-text-primary) !important;
134 }
135
136 .wrap .wp-list-table tr:nth-child(even) td {
137 background: var(--dashboard-card-bg) !important;
138 }
139
140 .wrap .wp-list-table tr:nth-child(odd) td {
141 background: rgba(255, 255, 255, 0.05) !important;
142 }
143
144 .wrap .wp-list-table tr:nth-child(even):hover td {
145 background: var(--dashboard-card-hover) !important;
146 color: var(--dashboard-text-primary) !important;
147 }
148
149 .wrap .wp-list-table tr:nth-child(odd):hover td {
150 background: var(--dashboard-card-hover) !important;
151 color: var(--dashboard-text-primary) !important;
152 }
153
154 /* Optimized table row backgrounds - alternating pattern for all rows */
155 .wrap .wp-list-table tbody tr:nth-child(odd) td {
156 background: var(--dashboard-card-bg) !important;
157 }
158
159 .wrap .wp-list-table tbody tr:nth-child(even) td {
160 background: rgba(255, 255, 255, 0.05) !important;
161 }
162
163 /* Ensure hover states work correctly */
164 .wrap .wp-list-table tbody tr:nth-child(odd):hover td {
165 background: var(--dashboard-card-hover) !important;
166 color: var(--dashboard-text-primary) !important;
167 }
168
169 .wrap .wp-list-table tbody tr:nth-child(even):hover td {
170 background: var(--dashboard-card-hover) !important;
171 color: var(--dashboard-text-primary) !important;
172 }
173
174 /* Button styling with higher specificity */
175 .wrap .button-primary,
176 .wrap .button-primary:visited,
177 .wrap input[type="submit"].button-primary,
178 .wrap input[type="button"].button-primary {
179 background: var(--dashboard-accent) !important;
180 border-color: var(--dashboard-accent) !important;
181 color: white !important;
182 border-radius: 8px !important;
183 font-weight: 500 !important;
184 transition: all 0.3s ease !important;
185 text-decoration: none !important;
186 }
187
188 .wrap .button-primary:hover,
189 .wrap .button-primary:focus,
190 .wrap input[type="submit"].button-primary:hover,
191 .wrap input[type="button"].button-primary:hover {
192 background: var(--dashboard-accent-hover) !important;
193 border-color: var(--dashboard-accent-hover) !important;
194 transform: translateY(-1px) !important;
195 box-shadow: var(--dashboard-shadow-hover) !important;
196 color: white !important;
197 text-decoration: none !important;
198 }
199
200 .wrap .button-secondary,
201 .wrap .button-secondary:visited,
202 .wrap input[type="submit"].button-secondary,
203 .wrap input[type="button"].button-secondary {
204 background: transparent !important;
205 border: 1px solid var(--dashboard-border) !important;
206 color: var(--dashboard-text-secondary) !important;
207 border-radius: 8px !important;
208 transition: all 0.3s ease !important;
209 text-decoration: none !important;
210 }
211
212 .wrap .button-secondary:hover,
213 .wrap .button-secondary:focus,
214 .wrap input[type="submit"].button-secondary:hover,
215 .wrap input[type="button"].button-secondary:hover {
216 background: var(--dashboard-card-hover) !important;
217 color: var(--dashboard-text-primary) !important;
218 border-color: var(--dashboard-accent) !important;
219 text-decoration: none !important;
220 }
221
222 /* Specific button targeting */
223 .wrap input[type="submit"]#doaction,
224 .wrap input[type="submit"]#post-query-submit,
225 .wrap input[type="submit"]#search-submit,
226 .wrap input[type="submit"].button {
227 background: var(--dashboard-accent) !important;
228 border-color: var(--dashboard-accent) !important;
229 color: white !important;
230 border-radius: 8px !important;
231 font-weight: 500 !important;
232 transition: all 0.3s ease !important;
233 }
234
235 .wrap input[type="submit"]#doaction:hover,
236 .wrap input[type="submit"]#post-query-submit:hover,
237 .wrap input[type="submit"]#search-submit:hover,
238 .wrap input[type="submit"].button:hover {
239 background: var(--dashboard-accent-hover) !important;
240 border-color: var(--dashboard-accent-hover) !important;
241 transform: translateY(-1px) !important;
242 box-shadow: var(--dashboard-shadow-hover) !important;
243 color: white !important;
244 }
245
246 /* Link button styling */
247 .wrap a.button,
248 .wrap a.button:visited {
249 background: var(--dashboard-accent) !important;
250 border-color: var(--dashboard-accent) !important;
251 color: white !important;
252 border-radius: 8px !important;
253 font-weight: 500 !important;
254 transition: all 0.3s ease !important;
255 text-decoration: none !important;
256 display: inline-block !important;
257 padding: 8px 16px !important;
258 }
259
260 .wrap a.button:hover,
261 .wrap a.button:focus {
262 background: var(--dashboard-accent-hover) !important;
263 border-color: var(--dashboard-accent-hover) !important;
264 transform: translateY(-1px) !important;
265 box-shadow: var(--dashboard-shadow-hover) !important;
266 color: white !important;
267 text-decoration: none !important;
268 }
269
270 /* Add Redirection Form Styling — hidden by default, shown via inline style by JS */
271 .wrap #add-redirection-form {
272 display: none;
273 background: var(--dashboard-card-bg) !important;
274 border: 1px solid var(--dashboard-border) !important;
275 border-radius: 12px !important;
276 padding: 24px !important;
277 margin-bottom: 24px !important;
278 box-shadow: var(--dashboard-shadow) !important;
279 }
280
281 .wrap #add-redirection-form h1 {
282 color: var(--dashboard-text-primary) !important;
283 margin-bottom: 20px !important;
284 font-size: 1.5rem !important;
285 font-weight: 600 !important;
286 }
287
288 .wrap #add-redirection-form .form-table {
289 background: transparent !important;
290 border: none !important;
291 }
292
293 .wrap #add-redirection-form .form-table th {
294 background: transparent !important;
295 color: var(--dashboard-text-primary) !important;
296 font-weight: 600 !important;
297 padding: 12px 0 !important;
298 width: 150px !important;
299 }
300
301 .wrap #add-redirection-form .form-table td {
302 background: transparent !important;
303 color: var(--dashboard-text-secondary) !important;
304 padding: 15px !important;
305 }
306
307 .wrap #add-redirection-form input[type="text"],
308 .wrap #add-redirection-form input[type="url"],
309 .wrap #add-redirection-form textarea {
310 background: var(--dashboard-card-hover) !important;
311 border: 1px solid var(--dashboard-border) !important;
312 color: var(--dashboard-text-primary) !important;
313 border-radius: 8px !important;
314 padding: 8px 12px !important;
315 width: 100% !important;
316 max-width: 500px !important;
317 }
318
319 .wrap #add-redirection-form input[type="text"]:focus,
320 .wrap #add-redirection-form input[type="url"]:focus,
321 .wrap #add-redirection-form textarea:focus {
322 border-color: var(--dashboard-accent) !important;
323 box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
324 outline: none !important;
325 }
326
327 .wrap #add-redirection-form textarea {
328 min-height: 80px !important;
329 resize: vertical !important;
330 }
331
332 .wrap #add-redirection-form input[type="radio"] {
333 margin-right: 8px !important;
334 accent-color: var(--dashboard-accent) !important;
335 }
336
337 .wrap #add-redirection-form label {
338 color: var(--dashboard-text-secondary) !important;
339 margin-right: 16px !important;
340 font-weight: 500 !important;
341 }
342
343 .wrap #add-redirection-form .source-url-list {
344 background: var(--dashboard-card-hover) !important;
345 border: 1px solid var(--dashboard-border) !important;
346 border-radius: 8px !important;
347 padding: 12px !important;
348 margin: 8px 0 !important;
349 }
350
351 .wrap #add-redirection-form .source-url-list li {
352 background: transparent !important;
353 border: none !important;
354 padding: 8px 0 !important;
355 margin: 0 !important;
356 display: flex !important;
357 align-items: center !important;
358 gap: 12px !important;
359 }
360
361 .wrap #add-redirection-form .source-url-list input[type="text"] {
362 flex: 1 !important;
363 max-width: none !important;
364 margin: 0 !important;
365 }
366
367 /* Target the actual select elements */
368 .wrap #add-redirection-form select[name="search_type[]"],
369 .wrap #add-redirection-form select {
370 background: var(--dashboard-card-hover) !important;
371 border: 1px solid var(--dashboard-border) !important;
372 color: var(--dashboard-text-primary) !important;
373 border-radius: 6px !important;
374 padding: 6px 8px !important;
375 min-width: 120px !important;
376 appearance: none !important;
377 -moz-appearance: none !important;
378 -webkit-appearance: none !important;
379 background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6,9 12,15 18,9'%3e%3c/polyline%3e%3c/svg%3e") !important;
380 background-repeat: no-repeat !important;
381 background-position: right 8px center !important;
382 background-size: 16px !important;
383 padding-right: 32px !important;
384 cursor: pointer !important;
385 margin-left: 8px !important;
386 }
387
388 .wrap #add-redirection-form select[name="search_type[]"]:focus,
389 .wrap #add-redirection-form select:focus {
390 border-color: var(--dashboard-accent) !important;
391 box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
392 outline: none !important;
393 }
394
395 .wrap #add-redirection-form select[name="search_type[]"] option,
396 .wrap #add-redirection-form select option {
397 background: var(--dashboard-card-hover) !important;
398 color: var(--dashboard-text-primary) !important;
399 padding: 8px !important;
400 }
401
402 /* Target the actual remove button class */
403 .wrap #add-redirection-form .source_url_delete,
404 .wrap #add-redirection-form button.source_url_delete {
405 background: var(--dashboard-error) !important;
406 border: 1px solid var(--dashboard-error) !important;
407 color: white !important;
408 border-radius: 6px !important;
409 padding: 6px 12px !important;
410 font-size: 12px !important;
411 font-weight: 500 !important;
412 transition: all 0.3s ease !important;
413 cursor: pointer !important;
414 display: inline-block !important;
415 margin-left: 8px !important;
416 }
417
418 .wrap #add-redirection-form .source_url_delete:hover,
419 .wrap #add-redirection-form button.source_url_delete:hover {
420 background: #dc2626 !important;
421 border-color: #dc2626 !important;
422 transform: translateY(-1px) !important;
423 color: white !important;
424 }
425
426 .wrap #add-redirection-form .add-source-url {
427 background: var(--dashboard-accent) !important;
428 border: 1px solid var(--dashboard-accent) !important;
429 color: white !important;
430 border-radius: 8px !important;
431 padding: 8px 16px !important;
432 font-weight: 500 !important;
433 transition: all 0.3s ease !important;
434 margin-top: 8px !important;
435 }
436
437 .wrap #add-redirection-form .add-source-url:hover {
438 background: var(--dashboard-accent-hover) !important;
439 border-color: var(--dashboard-accent-hover) !important;
440 transform: translateY(-1px) !important;
441 box-shadow: var(--dashboard-shadow-hover) !important;
442 }
443
444 .wrap #add-redirection-form .form-actions {
445 background: transparent !important;
446 border: none !important;
447 padding: 20px 0 0 0 !important;
448 margin-top: 20px !important;
449 border-top: 1px solid var(--dashboard-border) !important;
450 }
451
452 .wrap #add-redirection-form .form-actions input[type="submit"] {
453 background: var(--dashboard-accent) !important;
454 border: 1px solid var(--dashboard-accent) !important;
455 color: white !important;
456 border-radius: 8px !important;
457 padding: 10px 20px !important;
458 font-weight: 500 !important;
459 margin-right: 12px !important;
460 transition: all 0.3s ease !important;
461 }
462
463 .wrap #add-redirection-form .form-actions input[type="submit"]:hover {
464 background: var(--dashboard-accent-hover) !important;
465 border-color: var(--dashboard-accent-hover) !important;
466 transform: translateY(-1px) !important;
467 box-shadow: var(--dashboard-shadow-hover) !important;
468 }
469
470 .wrap #add-redirection-form .form-actions input[type="button"] {
471 background: transparent !important;
472 border: 1px solid var(--dashboard-border) !important;
473 color: var(--dashboard-text-secondary) !important;
474 border-radius: 8px !important;
475 padding: 10px 20px !important;
476 font-weight: 500 !important;
477 transition: all 0.3s ease !important;
478 }
479
480 .wrap #add-redirection-form .form-actions input[type="button"]:hover {
481 background: var(--dashboard-card-hover) !important;
482 color: var(--dashboard-text-primary) !important;
483 border-color: var(--dashboard-accent) !important;
484 }
485
486 /* Additional form element styling */
487 .wrap #add-redirection-form input[type="radio"]:checked {
488 accent-color: var(--dashboard-accent) !important;
489 }
490
491 .wrap #add-redirection-form input[type="radio"]:checked + label {
492 color: var(--dashboard-text-primary) !important;
493 font-weight: 600 !important;
494 }
495
496 /* Ensure all buttons in the form are properly styled */
497 .wrap #add-redirection-form button,
498 .wrap #add-redirection-form input[type="button"],
499 .wrap #add-redirection-form input[type="submit"] {
500 font-family: inherit !important;
501 font-size: 14px !important;
502 line-height: 1.4 !important;
503 vertical-align: middle !important;
504 }
505
506 /* Fix any remaining button styling issues */
507 .wrap #add-redirection-form .button,
508 .wrap #add-redirection-form .button-secondary {
509 background: transparent !important;
510 border: 1px solid var(--dashboard-border) !important;
511 color: var(--dashboard-text-secondary) !important;
512 border-radius: 8px !important;
513 padding: 8px 16px !important;
514 font-weight: 500 !important;
515 transition: all 0.3s ease !important;
516 text-decoration: none !important;
517 display: inline-block !important;
518 cursor: pointer !important;
519 }
520
521 .wrap #add-redirection-form .button:hover,
522 .wrap #add-redirection-form .button-secondary:hover {
523 background: var(--dashboard-card-hover) !important;
524 color: var(--dashboard-text-primary) !important;
525 border-color: var(--dashboard-accent) !important;
526 text-decoration: none !important;
527 }
528
529 /* Additional targeting for form elements */
530 .wrap #add-redirection-form #source_urls li {
531 display: flex !important;
532 align-items: center !important;
533 gap: 8px !important;
534 margin-bottom: 8px !important;
535 padding: 8px !important;
536 background: var(--dashboard-card-hover) !important;
537 border-radius: 8px !important;
538 border: 1px solid var(--dashboard-border) !important;
539 }
540
541 .wrap #add-redirection-form #source_urls li input[type="text"] {
542 flex: 1 !important;
543 background: var(--dashboard-card-bg) !important;
544 border: 1px solid var(--dashboard-border) !important;
545 color: var(--dashboard-text-primary) !important;
546 border-radius: 6px !important;
547 padding: 6px 8px !important;
548 }
549
550 /* Force override for any conflicting styles */
551 .wrap #add-redirection-form * {
552 box-sizing: border-box !important;
553 }
554
555 /* Page headers and content */
556 .wp-heading-inline {
557 color: var(--dashboard-text-primary) !important;
558 }
559
560 h1, h2, h3 {
561 color: var(--dashboard-text-primary) !important;
562 }
563
564 /* Tablenav styling */
565 /* ── Tablenav ── */
566 .wrap .tablenav {
567 background: var(--dashboard-card-bg);
568 border: 1px solid var(--dashboard-border);
569 border-radius: 8px;
570 padding: 12px 16px;
571 margin-bottom: 16px;
572 box-shadow: var(--dashboard-shadow);
573 display: flex;
574 align-items: center;
575 flex-wrap: wrap;
576 gap: 8px;
577 }
578 .wrap .tablenav * { box-sizing: border-box; margin: 0; }
579
580 /* Left group: filters / bulk actions — shrinks equally with search */
581 .wrap .tablenav .alignleft,
582 .wrap .tablenav .actions {
583 display: flex;
584 align-items: center;
585 flex-wrap: nowrap;
586 gap: 6px;
587 flex: 1 1 0;
588 min-width: 0;
589 }
590
591 /* Right group: pagination */
592 .wrap .tablenav .alignright {
593 display: flex;
594 align-items: center;
595 flex-wrap: wrap;
596 gap: 6px;
597 margin-left: auto;
598 min-width: 0;
599 }
600
601 /* Search box — sits inline with filters, shrinks to fit */
602 .wrap .tablenav .metasync-search-box {
603 display: flex;
604 align-items: center;
605 flex-wrap: nowrap;
606 gap: 6px;
607 flex: 1 1 0;
608 min-width: 0;
609 }
610 .wrap .tablenav .metasync-search-box input[type="search"] {
611 flex: 1 1 60px;
612 min-width: 0;
613 width: auto;
614 }
615
616 /* ── Shared control height ── */
617 .wrap .tablenav select,
618 .wrap .tablenav input[type="search"],
619 .wrap .tablenav input[type="text"],
620 .wrap .tablenav input[type="submit"],
621 .wrap .tablenav input[type="button"],
622 .wrap .tablenav .button {
623 height: 34px;
624 font-size: 13px;
625 font-weight: 500;
626 border-radius: 6px;
627 padding: 0 10px;
628 line-height: 34px;
629 }
630
631 /* Selects — shrinkable, text truncates when compressed */
632 .wrap .tablenav select {
633 background: var(--dashboard-card-bg);
634 border: 1px solid var(--dashboard-border);
635 color: var(--dashboard-text-primary);
636 appearance: none;
637 -webkit-appearance: none;
638 background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6,9 12,15 18,9'%3e%3c/polyline%3e%3c/svg%3e");
639 background-repeat: no-repeat;
640 background-position: right 6px center;
641 background-size: 14px;
642 padding-right: 28px;
643 cursor: pointer;
644 flex: 1 1 0;
645 min-width: 0;
646 overflow: hidden;
647 text-overflow: ellipsis;
648 }
649 .wrap .tablenav select:focus {
650 border-color: var(--dashboard-accent);
651 box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
652 outline: none;
653 }
654 .wrap .tablenav select option {
655 background: var(--dashboard-card-bg);
656 color: var(--dashboard-text-primary);
657 }
658
659 /* Text / search inputs — fully flexible */
660 .wrap .tablenav input[type="search"],
661 .wrap .tablenav input[type="text"] {
662 background: var(--dashboard-card-bg);
663 border: 1px solid var(--dashboard-border);
664 color: var(--dashboard-text-primary);
665 width: auto;
666 min-width: 0;
667 flex: 1 1 80px;
668 }
669 .wrap .tablenav input[type="search"]:focus,
670 .wrap .tablenav input[type="text"]:focus {
671 border-color: var(--dashboard-accent);
672 box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
673 outline: none;
674 }
675
676 /* Pagination current-page — narrow */
677 .wrap .tablenav-pages input.current-page,
678 .wrap .tablenav .current-page {
679 width: 3em !important;
680 min-width: 3em !important;
681 flex: 0 0 3em !important;
682 text-align: center;
683 padding: 0 4px;
684 }
685
686 /* Buttons */
687 .wrap .tablenav input[type="submit"],
688 .wrap .tablenav input[type="button"],
689 .wrap .tablenav .button {
690 white-space: nowrap;
691 display: inline-flex;
692 align-items: center;
693 justify-content: center;
694 flex-shrink: 0;
695 }
696
697
698 /* Item count badge */
699 .wrap .tablenav .displaying-num {
700 color: var(--dashboard-text-primary);
701 font-size: 12px;
702 font-weight: 500;
703 background: var(--dashboard-card-hover);
704 padding: 0 10px;
705 border-radius: 6px;
706 border: 1px solid var(--dashboard-border);
707 height: 30px;
708 line-height: 28px;
709 white-space: nowrap;
710 }
711
712 /* Pagination controls */
713 .wrap .tablenav-pages {
714 display: flex;
715 align-items: center;
716 gap: 4px;
717 margin-left: auto;
718 flex-wrap: wrap;
719 }
720 .wrap .tablenav-pages .paging-input {
721 display: inline-flex;
722 align-items: center;
723 gap: 4px;
724 }
725 .wrap .tablenav .alignright span,
726 .wrap .tablenav .alignright p {
727 color: var(--dashboard-text-primary);
728 font-size: 12px;
729 padding: 0;
730 border: none;
731 background: transparent;
732 height: auto;
733 }
734
735 .wrap .tablenav label {
736 padding: 0;
737 white-space: nowrap;
738 font-weight: 500;
739 color: var(--dashboard-text-primary);
740 font-size: 13px;
741 }
742
743 /* Page title action styling */
744 .page-title-action {
745 background: var(--dashboard-accent) !important;
746 border-color: var(--dashboard-accent) !important;
747 color: white !important;
748 border-radius: 8px !important;
749 font-weight: 500 !important;
750 transition: all 0.3s ease !important;
751 text-decoration: none !important;
752 padding: 8px 16px !important;
753 display: inline-flex !important;
754 align-items: center !important;
755 gap: 8px !important;
756 }
757 .page-title-action:hover {
758 background: var(--dashboard-accent-hover) !important;
759 border-color: var(--dashboard-accent-hover) !important;
760 transform: translateY(-1px);
761 box-shadow: var(--dashboard-shadow-hover) !important;
762 color: white !important;
763 }
764
765 /* Status indicators */
766 .status-active { color: var(--dashboard-success) !important; font-weight: 600; }
767 .status-inactive { color: var(--dashboard-text-secondary) !important; font-weight: 600; }
768
769 /* HTTP code styling */
770 .http-code-301, .http-code-302, .http-code-307 { color: var(--dashboard-accent) !important; font-weight: 600; }
771 .http-code-410, .http-code-451 { color: var(--dashboard-warning) !important; font-weight: 600; }
772
773 /* Duplicate element guards */
774 .wrap .wp-list-table + .wp-list-table { display: none !important; }
775 .wrap .tablenav + .tablenav { display: none !important; }
776 .wrap .wp-list-table thead:not(:first-of-type) { display: none !important; }
777 .wrap .wp-list-table tfoot { display: none !important; }
778
779 /* ── Responsive ── */
780 @media (max-width: 1200px) {
781 .wrap .tablenav { padding: 10px 12px; gap: 6px; }
782 .wrap .tablenav select,
783 .wrap .tablenav input[type="search"],
784 .wrap .tablenav input[type="text"],
785 .wrap .tablenav input[type="submit"],
786 .wrap .tablenav .button {
787 height: 30px; font-size: 12px; line-height: 30px; padding: 0 8px;
788 }
789 .wrap .tablenav select { padding-right: 22px; background-size: 12px; }
790 }
791
792 @media (max-width: 782px) {
793 .wrap .tablenav { padding: 10px; gap: 8px; }
794 .wrap .tablenav .alignleft,
795 .wrap .tablenav .alignright,
796 .wrap .tablenav .actions,
797 .wrap .tablenav .metasync-search-box { width: 100%; flex: 1 1 100%; }
798 .wrap .tablenav select { flex: 1 1 0%; }
799 .wrap .tablenav-pages { margin-left: 0; width: 100%; justify-content: center; }
800 }
801
802 /* Description text styling */
803 .wrap .description,
804 .wrap p.description {
805 color: var(--dashboard-text-secondary, #9ca3af) !important;
806 font-size: 13px !important;
807 line-height: 1.5 !important;
808 }
809
810 /* Health status column */
811 .column-health_status { width: 7%; text-align: center; }
812 .health-status-cell { display: inline-block; cursor: default; font-size: 16px; }
813
814 /* Body-appended floating tooltip — escapes all table stacking contexts */
815 .health-tooltip-floating {
816 position: fixed;
817 display: block;
818 background: #1e293b;
819 border: 1px solid #475569;
820 border-radius: 6px;
821 padding: 6px 12px;
822 z-index: 999999;
823 white-space: nowrap;
824 font-size: 12px;
825 color: #cbd5e1;
826 box-shadow: 0 4px 16px rgba(0,0,0,0.6);
827 pointer-events: none;
828 }
829 .wrap .wp-list-table thead tr:first-child th:first-child { border-top-left-radius: 12px; }
830 .wrap .wp-list-table thead tr:first-child th:last-child { border-top-right-radius: 12px; }
831 .wrap .wp-list-table tbody tr:last-child td:first-child { border-bottom-left-radius: 12px; }
832 .wrap .wp-list-table tbody tr:last-child td:last-child { border-bottom-right-radius: 12px; }
833 </style>
834
835 <div class="wrap">
836 <a href="<?php echo esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-redirections&action=add')); ?>" class="page-title-action">Add New Redirect</a>
837
838 <!-- Import from SEO Plugins Button -->
839 <a href="<?php echo esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-import-external&tab=redirections')); ?>" class="page-title-action" style="background: #10b981 !important; border-color: #10b981 !important;">
840 <span>📥</span> Import from SEO Plugins
841 </a>
842
843 <!-- Check Health Button -->
844 <button type="button" id="metasync-check-health-btn" class="page-title-action" style="background: #f59e0b !important; border-color: #f59e0b !important; color: #000 !important;">
845 Check Health
846 </button>
847
848 <!-- Allow External Redirects Setting -->
849 <?php
850 if (isset($_POST['metasync_save_external_redirects']) && current_user_can('manage_options') && wp_verify_nonce($_POST['_metasync_external_nonce'], 'metasync_external_redirects_toggle')) {
851 $allow_external = isset($_POST['metasync_allow_external_redirects']) ? 1 : 0;
852 update_option('metasync_allow_external_redirects', $allow_external, true);
853 echo '<div class="notice notice-success is-dismissible"><p>External redirects setting updated.</p></div>';
854 }
855 $allow_external_current = get_option('metasync_allow_external_redirects', 0);
856 ?>
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;">
858 <form method="post" style="display: flex; align-items: center; gap: 12px; margin: 0;">
859 <?php wp_nonce_field('metasync_external_redirects_toggle', '_metasync_external_nonce'); ?>
860 <label style="display: flex; align-items: center; gap: 8px; cursor: pointer; color: var(--dashboard-text-primary, #fff); font-weight: 500;">
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;">
862 Allow External Redirects
863 </label>
864 <input type="hidden" name="metasync_save_external_redirects" value="1">
865 <?php if ($allow_external_current) : ?>
866 <span style="color: var(--dashboard-warning, #f59e0b); font-size: 13px;">External redirects are enabled. Redirects can point to other websites.</span>
867 <?php else : ?>
868 <span style="color: var(--dashboard-text-secondary, #9ca3af); font-size: 13px;">External redirects are disabled. All redirects will stay on your site for security.</span>
869 <?php endif; ?>
870 </form>
871 </div>
872
873 <!-- Forms are NOT created automatically, so you need to wrap the table in one to use features like bulk actions -->
874 <form id="redirection-form" method="post" action="">
875 <?php wp_nonce_field('metasync_redirection_form', 'metasync_redirection_nonce'); ?>
876 <?php include "metasync-add-redirection.php";
877 $request_data = metasync_sanitize_input_array($_REQUEST); ?>
878 <!-- For plugins, we also need to ensure that the form posts back to our current page -->
879 <input type="hidden" name="page" value="<?php echo esc_attr($request_data['page']) ?>" />
880
881 <!-- Search and Filter Controls -->
882 <div class="tablenav top">
883
884 <div class="alignleft actions">
885 <label for="status-filter" class="screen-reader-text">Filter by status</label>
886 <select name="status_filter" id="status-filter">
887 <option value="">All Statuses</option>
888 <option value="active" <?php selected(isset($_REQUEST['status_filter']) ? $_REQUEST['status_filter'] : '', 'active'); ?>>Active</option>
889 <option value="inactive" <?php selected(isset($_REQUEST['status_filter']) ? $_REQUEST['status_filter'] : '', 'inactive'); ?>>Inactive</option>
890 </select>
891
892 <label for="pattern-filter" class="screen-reader-text">Filter by pattern type</label>
893 <select name="pattern_filter" id="pattern-filter">
894 <option value="">All Patterns</option>
895 <option value="exact" <?php selected(isset($_REQUEST['pattern_filter']) ? $_REQUEST['pattern_filter'] : '', 'exact'); ?>>Exact Match</option>
896 <option value="start" <?php selected(isset($_REQUEST['pattern_filter']) ? $_REQUEST['pattern_filter'] : '', 'start'); ?>>Starts With</option>
897 <option value="end" <?php selected(isset($_REQUEST['pattern_filter']) ? $_REQUEST['pattern_filter'] : '', 'end'); ?>>Ends With</option>
898 <option value="wildcard" <?php selected(isset($_REQUEST['pattern_filter']) ? $_REQUEST['pattern_filter'] : '', 'wildcard'); ?>>Wildcard (*)</option>
899 <option value="regex" <?php selected(isset($_REQUEST['pattern_filter']) ? $_REQUEST['pattern_filter'] : '', 'regex'); ?>>Regex Pattern</option>
900 </select>
901
902 <label for="http-code-filter" class="screen-reader-text">Filter by HTTP code</label>
903 <select name="http_code_filter" id="http-code-filter">
904 <option value="">All Types</option>
905 <option value="301" <?php selected(isset($_REQUEST['http_code_filter']) ? $_REQUEST['http_code_filter'] : '', '301'); ?>>301 Permanent</option>
906 <option value="302" <?php selected(isset($_REQUEST['http_code_filter']) ? $_REQUEST['http_code_filter'] : '', '302'); ?>>302 Temporary</option>
907 <option value="307" <?php selected(isset($_REQUEST['http_code_filter']) ? $_REQUEST['http_code_filter'] : '', '307'); ?>>307 Temporary</option>
908 <option value="410" <?php selected(isset($_REQUEST['http_code_filter']) ? $_REQUEST['http_code_filter'] : '', '410'); ?>>410 Gone</option>
909 <option value="451" <?php selected(isset($_REQUEST['http_code_filter']) ? $_REQUEST['http_code_filter'] : '', '451'); ?>>451 Unavailable</option>
910 </select>
911
912 <input type="submit" name="filter_action" id="post-query-submit" class="button" value="Filter">
913 </div>
914
915 <div class="metasync-search-box">
916 <label class="screen-reader-text" for="post-search-input">Search Redirections:</label>
917 <input type="search" id="post-search-input" name="s" value="<?php echo esc_attr(isset($_REQUEST['s']) ? $_REQUEST['s'] : ''); ?>" placeholder="Search redirections...">
918 <input type="submit" id="search-submit" class="button" value="Search">
919 </div>
920 </div>
921
922 <!-- Now we can render the completed list table -->
923 <?php $MetasyncRedirection->display() ?>
924 </form>
925
926 </div>
927
928