diff --git a/admin/class-wpcm-admin.php b/admin/class-wpcm-admin.php index eb3a785..4a916e7 100644 --- a/admin/class-wpcm-admin.php +++ b/admin/class-wpcm-admin.php @@ -77,6 +77,15 @@ public function add_admin_menu() { array($this, 'render_rankings') ); + add_submenu_page( + 'wpcm-dashboard', + __('Known Conflicts', 'wp-plugin-conflict-mapper'), + __('Known Conflicts', 'wp-plugin-conflict-mapper'), + 'manage_options', + 'wpcm-known-conflicts', + array($this, 'render_known_conflicts') + ); + add_submenu_page( 'wpcm-dashboard', __('Settings', 'wp-plugin-conflict-mapper'), @@ -199,6 +208,21 @@ public function render_rankings() { include WPCM_PLUGIN_DIR . 'admin/views/rankings.php'; } + /** + * Render known conflicts page + * + * @return void + */ + public function render_known_conflicts() { + $minimal_scanner = new WPCM_Minimal_Scanner(); + + $scan_results = $minimal_scanner->quick_scan(true); + $db_stats = $minimal_scanner->get_database_stats(); + $recommendations = $minimal_scanner->get_recommendations($scan_results['conflicts']); + + include WPCM_PLUGIN_DIR . 'admin/views/known-conflicts.php'; + } + /** * Render settings page * diff --git a/admin/views/known-conflicts.php b/admin/views/known-conflicts.php new file mode 100644 index 0000000..786f0b9 --- /dev/null +++ b/admin/views/known-conflicts.php @@ -0,0 +1,308 @@ + + +
+

+ + +

+ +

+ +

+ + +
+
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+
+ + +
+
+

+
+ array('count' => $scan_results['critical_conflicts'], 'color' => '#d63638', 'label' => __('Critical', 'wp-plugin-conflict-mapper')), + 'high' => array('count' => $scan_results['high_conflicts'], 'color' => '#e65100', 'label' => __('High', 'wp-plugin-conflict-mapper')), + 'medium' => array('count' => $scan_results['medium_conflicts'], 'color' => '#dba617', 'label' => __('Medium', 'wp-plugin-conflict-mapper')), + 'low' => array('count' => $scan_results['low_conflicts'], 'color' => '#72aee6', 'label' => __('Low', 'wp-plugin-conflict-mapper')), + ); + ?> + 0): ?> +
+ $sev): ?> + 0): ?> +
+
+
+
+ +
+
+
+ + +
+ +
+ +

+
+ +
+
+ +
+

+
+ array('count' => $scan_results['conflicts_by_type']['overlap'], 'icon' => 'admin-page', 'color' => '#9b59b6', 'label' => __('Overlap', 'wp-plugin-conflict-mapper')), + 'conflict' => array('count' => $scan_results['conflicts_by_type']['conflict'], 'icon' => 'dismiss', 'color' => '#e74c3c', 'label' => __('Conflict', 'wp-plugin-conflict-mapper')), + 'incompatible' => array('count' => $scan_results['conflicts_by_type']['incompatible'], 'icon' => 'no', 'color' => '#34495e', 'label' => __('Incompatible', 'wp-plugin-conflict-mapper')), + 'performance' => array('count' => $scan_results['conflicts_by_type']['performance'], 'icon' => 'performance', 'color' => '#f39c12', 'label' => __('Performance', 'wp-plugin-conflict-mapper')), + ); + ?> +
+ $type): ?> +
+ + + +
+ +
+
+
+
+ + + +
+

+ + +

+ +
+ + +
+ +
+ + '#d63638', + 'high' => '#e65100', + 'medium' => '#dba617', + 'low' => '#72aee6', + ); + $severity_icons = array( + 'critical' => 'megaphone', + 'high' => 'flag', + 'medium' => 'info', + 'low' => 'marker', + ); + ?> +
+
+ + + + + + + +
+ +
+
+ + + + + + + + + + + +
+
+ +
+

+
+ +
+ + + + +

+
+ + +
+ + +
+ +
+ +
+
+ + + +
+

+ + +

+ +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+

+
+
+

+
    +
  • +
  • +
  • +
  • +
+
+
+

+
    +
  • +
  • +
  • +
  • +
+
+
+
+
+ + +
+

+ + +

+

+ +
+ + + +
diff --git a/assets/css/admin.css b/assets/css/admin.css index ac7c539..6a19b04 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -372,3 +372,594 @@ margin: 10% auto; } } + +/* ========================================================================== + Known Conflicts Visualization Styles + ========================================================================== */ + +/* Subtitle */ +.wpcm-known-conflicts .wpcm-subtitle { + font-size: 14px; + color: #646970; + margin: -10px 0 20px; +} + +/* Summary Cards */ +.wpcm-conflict-summary { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: 15px; + margin: 25px 0; +} + +.wpcm-summary-card { + background: #fff; + border: 1px solid #e0e0e0; + border-radius: 8px; + padding: 20px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + transition: transform 0.2s, box-shadow 0.2s; +} + +.wpcm-summary-card:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0,0,0,0.1); +} + +.wpcm-summary-icon { + width: 50px; + height: 50px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 12px; + background: #f0f6fc; +} + +.wpcm-summary-icon .dashicons { + font-size: 24px; + width: 24px; + height: 24px; + color: #2271b1; +} + +.wpcm-summary-total .wpcm-summary-icon { background: #f0f6fc; } +.wpcm-summary-total .wpcm-summary-icon .dashicons { color: #2271b1; } + +.wpcm-summary-found .wpcm-summary-icon { background: #edfaef; } +.wpcm-summary-found .wpcm-summary-icon .dashicons { color: #00a32a; } +.wpcm-summary-found.has-conflicts .wpcm-summary-icon { background: #fcf0f1; } +.wpcm-summary-found.has-conflicts .wpcm-summary-icon .dashicons { color: #d63638; } + +.wpcm-summary-critical .wpcm-summary-icon { background: #f0f0f1; } +.wpcm-summary-critical .wpcm-summary-icon .dashicons { color: #646970; } +.wpcm-summary-critical.has-issues .wpcm-summary-icon { background: #fcf0f1; } +.wpcm-summary-critical.has-issues .wpcm-summary-icon .dashicons { color: #d63638; } + +.wpcm-summary-high .wpcm-summary-icon { background: #f0f0f1; } +.wpcm-summary-high .wpcm-summary-icon .dashicons { color: #646970; } +.wpcm-summary-high.has-issues .wpcm-summary-icon { background: #fff3e0; } +.wpcm-summary-high.has-issues .wpcm-summary-icon .dashicons { color: #e65100; } + +.wpcm-summary-medium .wpcm-summary-icon { background: #fef8e7; } +.wpcm-summary-medium .wpcm-summary-icon .dashicons { color: #dba617; } + +.wpcm-summary-low .wpcm-summary-icon { background: #f0f6fc; } +.wpcm-summary-low .wpcm-summary-icon .dashicons { color: #72aee6; } + +.wpcm-summary-number { + font-size: 32px; + font-weight: 700; + line-height: 1; + color: #1d2327; +} + +.wpcm-summary-label { + font-size: 12px; + color: #646970; + margin-top: 5px; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +/* Charts Row */ +.wpcm-charts-row { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); + gap: 20px; + margin: 30px 0; +} + +.wpcm-chart-container { + background: #fff; + border: 1px solid #e0e0e0; + border-radius: 8px; + padding: 25px; +} + +.wpcm-chart-container h2 { + margin: 0 0 20px; + font-size: 16px; + font-weight: 600; +} + +/* Bar Chart */ +.wpcm-bar-chart { + display: flex; + flex-direction: column; + gap: 12px; +} + +.wpcm-bar-item { + display: flex; + align-items: center; + gap: 10px; +} + +.wpcm-bar-label { + width: 70px; + font-size: 13px; + font-weight: 500; + color: #1d2327; +} + +.wpcm-bar-track { + flex: 1; + height: 28px; + background: #f0f0f1; + border-radius: 4px; + overflow: hidden; +} + +.wpcm-bar-fill { + height: 100%; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: flex-end; + padding-right: 10px; + min-width: 35px; + transition: width 0.5s ease; +} + +.wpcm-bar-value { + color: #fff; + font-size: 12px; + font-weight: 600; +} + +/* No Conflicts State */ +.wpcm-no-conflicts { + text-align: center; + padding: 40px 20px; + color: #00a32a; +} + +.wpcm-no-conflicts .dashicons { + font-size: 48px; + width: 48px; + height: 48px; + margin-bottom: 10px; +} + +.wpcm-no-conflicts p { + font-size: 16px; + margin: 0; +} + +/* Type Grid */ +.wpcm-type-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 15px; +} + +.wpcm-type-item { + background: #f6f7f7; + border-radius: 8px; + padding: 20px; + text-align: center; + transition: background 0.2s; +} + +.wpcm-type-item.has-issues { + background: #fcf0f1; +} + +.wpcm-type-item .dashicons { + font-size: 28px; + width: 28px; + height: 28px; + margin-bottom: 8px; +} + +.wpcm-type-count { + display: block; + font-size: 24px; + font-weight: 700; + color: #1d2327; +} + +.wpcm-type-label { + font-size: 12px; + color: #646970; + text-transform: uppercase; +} + +/* Conflicts List */ +.wpcm-conflicts-list { + background: #fff; + border: 1px solid #e0e0e0; + border-radius: 8px; + padding: 25px; + margin: 30px 0; +} + +.wpcm-conflicts-list h2 { + margin: 0 0 20px; + font-size: 18px; + display: flex; + align-items: center; + gap: 8px; +} + +.wpcm-conflicts-list h2 .dashicons { + color: #2271b1; +} + +/* Filter Bar */ +.wpcm-filter-bar { + background: #f6f7f7; + padding: 12px 15px; + border-radius: 6px; + margin-bottom: 20px; + display: flex; + align-items: center; + gap: 10px; +} + +.wpcm-filter-bar label { + font-weight: 500; + color: #1d2327; +} + +.wpcm-filter-select { + min-width: 150px; +} + +/* Conflicts Grid */ +.wpcm-conflicts-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); + gap: 20px; +} + +/* Conflict Card */ +.wpcm-conflict-card { + background: #fff; + border: 1px solid #e0e0e0; + border-radius: 8px; + overflow: hidden; + transition: box-shadow 0.2s; +} + +.wpcm-conflict-card:hover { + box-shadow: 0 4px 12px rgba(0,0,0,0.1); +} + +.wpcm-conflict-card.hidden { + display: none; +} + +.wpcm-conflict-header { + background: #f6f7f7; + padding: 12px 15px; + display: flex; + justify-content: space-between; + align-items: center; + border-left: 4px solid #d63638; +} + +.wpcm-severity-badge { + display: inline-flex; + align-items: center; + gap: 5px; + padding: 4px 10px; + border-radius: 4px; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + color: #fff; +} + +.wpcm-severity-badge .dashicons { + font-size: 14px; + width: 14px; + height: 14px; +} + +.wpcm-severity-critical { background: #d63638; } +.wpcm-severity-high { background: #e65100; } +.wpcm-severity-medium { background: #dba617; } +.wpcm-severity-low { background: #72aee6; } + +.wpcm-conflict-type { + font-size: 11px; + font-weight: 500; + text-transform: uppercase; + padding: 4px 8px; + border-radius: 4px; + background: #e0e0e0; + color: #1d2327; +} + +.wpcm-type-overlap { background: #f3e5f5; color: #7b1fa2; } +.wpcm-type-conflict { background: #ffebee; color: #c62828; } +.wpcm-type-incompatible { background: #eceff1; color: #37474f; } +.wpcm-type-performance { background: #fff8e1; color: #f57f17; } + +/* Plugin Pair */ +.wpcm-conflict-plugins { + padding: 15px; + border-bottom: 1px solid #f0f0f1; +} + +.wpcm-plugin-pair { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; +} + +.wpcm-plugin-name { + flex: 1; + display: flex; + align-items: center; + gap: 6px; + font-weight: 500; + color: #1d2327; + font-size: 13px; +} + +.wpcm-plugin-name .dashicons { + color: #2271b1; + font-size: 16px; + width: 16px; + height: 16px; +} + +.wpcm-conflict-icon { + color: #d63638; +} + +.wpcm-conflict-icon .dashicons { + font-size: 20px; + width: 20px; + height: 20px; +} + +/* Conflict Description & Resolution */ +.wpcm-conflict-description, +.wpcm-conflict-resolution { + padding: 12px 15px; + font-size: 13px; + line-height: 1.5; +} + +.wpcm-conflict-description { + border-bottom: 1px solid #f0f0f1; + color: #1d2327; +} + +.wpcm-conflict-description p, +.wpcm-conflict-resolution p { + margin: 0; +} + +.wpcm-conflict-resolution { + background: #f0f6fc; +} + +.wpcm-conflict-resolution strong { + display: flex; + align-items: center; + gap: 5px; + color: #2271b1; + margin-bottom: 5px; +} + +.wpcm-conflict-resolution strong .dashicons { + font-size: 16px; + width: 16px; + height: 16px; +} + +.wpcm-conflict-resolution p { + color: #1d2327; +} + +/* Verified Badge */ +.wpcm-verified-badge { + display: flex; + align-items: center; + gap: 5px; + padding: 8px 15px; + background: #edfaef; + color: #00a32a; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; +} + +.wpcm-verified-badge .dashicons { + font-size: 14px; + width: 14px; + height: 14px; +} + +/* Database Stats */ +.wpcm-db-stats { + background: #fff; + border: 1px solid #e0e0e0; + border-radius: 8px; + padding: 25px; + margin: 30px 0; +} + +.wpcm-db-stats h2 { + margin: 0 0 20px; + font-size: 18px; + display: flex; + align-items: center; + gap: 8px; +} + +.wpcm-db-stats h2 .dashicons { + color: #2271b1; +} + +.wpcm-db-stats-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; + margin-bottom: 25px; +} + +.wpcm-db-stat { + text-align: center; + padding: 20px; + background: #f6f7f7; + border-radius: 8px; +} + +.wpcm-db-stat-value { + display: block; + font-size: 36px; + font-weight: 700; + color: #2271b1; + line-height: 1; +} + +.wpcm-db-stat-label { + display: block; + font-size: 12px; + color: #646970; + margin-top: 8px; + text-transform: uppercase; +} + +/* Breakdown */ +.wpcm-db-breakdown h3 { + margin: 0 0 15px; + font-size: 14px; + color: #1d2327; +} + +.wpcm-breakdown-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 30px; +} + +.wpcm-breakdown-section h4 { + margin: 0 0 10px; + font-size: 13px; + color: #646970; + text-transform: uppercase; +} + +.wpcm-breakdown-section ul { + list-style: none; + margin: 0; + padding: 0; +} + +.wpcm-breakdown-section li { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 0; + font-size: 13px; + color: #1d2327; +} + +.wpcm-dot { + width: 10px; + height: 10px; + border-radius: 50%; + flex-shrink: 0; +} + +/* Export Section */ +.wpcm-export-section { + background: #fff; + border: 1px solid #e0e0e0; + border-radius: 8px; + padding: 25px; + margin: 30px 0; +} + +.wpcm-export-section h2 { + margin: 0 0 10px; + font-size: 18px; + display: flex; + align-items: center; + gap: 8px; +} + +.wpcm-export-section h2 .dashicons { + color: #2271b1; +} + +.wpcm-export-section p { + color: #646970; + margin: 0 0 15px; +} + +.wpcm-export-section .button { + display: inline-flex; + align-items: center; + gap: 5px; +} + +.wpcm-export-section .button .dashicons { + font-size: 16px; + width: 16px; + height: 16px; +} + +/* Known Conflicts Responsive */ +@media screen and (max-width: 782px) { + .wpcm-conflict-summary { + grid-template-columns: repeat(2, 1fr); + } + + .wpcm-charts-row { + grid-template-columns: 1fr; + } + + .wpcm-conflicts-grid { + grid-template-columns: 1fr; + } + + .wpcm-db-stats-grid { + grid-template-columns: 1fr; + } + + .wpcm-breakdown-grid { + grid-template-columns: 1fr; + } + + .wpcm-plugin-pair { + flex-direction: column; + text-align: center; + } + + .wpcm-conflict-icon { + transform: rotate(90deg); + } +} diff --git a/assets/js/admin.js b/assets/js/admin.js index 7f967d0..0008bd2 100644 --- a/assets/js/admin.js +++ b/assets/js/admin.js @@ -23,6 +23,8 @@ this.showIssues(); this.modal(); this.cleanupScans(); + this.knownConflictsFilter(); + this.knownConflictsExport(); }, /** @@ -225,8 +227,9 @@ /** * Download file */ - downloadFile: function(content, filename) { - var blob = new Blob([content], { type: 'text/plain' }); + downloadFile: function(content, filename, contentType) { + contentType = contentType || 'text/plain'; + var blob = new Blob([content], { type: contentType }); var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = filename; @@ -431,6 +434,88 @@ $(this).remove(); }); }, 5000); + }, + + /** + * Known conflicts severity filter + */ + knownConflictsFilter: function() { + $('#wpcm-severity-filter').on('change', function() { + var filter = $(this).val(); + var $cards = $('.wpcm-conflict-card'); + + if (filter === 'all') { + $cards.removeClass('hidden').fadeIn(200); + } else { + $cards.each(function() { + var severity = $(this).data('severity'); + if (severity === filter) { + $(this).removeClass('hidden').fadeIn(200); + } else { + $(this).addClass('hidden').fadeOut(200); + } + }); + } + + // Update visible count + var visibleCount = $cards.filter(':not(.hidden)').length; + WPCM_Admin.updateFilterStatus(visibleCount, $cards.length); + }); + }, + + /** + * Update filter status message + */ + updateFilterStatus: function(visible, total) { + var $status = $('#wpcm-filter-status'); + if ($status.length === 0) { + $status = $(''); + $('#wpcm-severity-filter').after($status); + } + if (visible < total) { + $status.text('Showing ' + visible + ' of ' + total + ' conflicts'); + } else { + $status.text(''); + } + }, + + /** + * Export known conflicts as JSON + */ + knownConflictsExport: function() { + $('#wpcm-export-json').on('click', function(e) { + e.preventDefault(); + + var $scanData = $('#wpcm-scan-data'); + if ($scanData.length === 0) { + WPCM_Admin.showNotice('No scan data available to export', 'error'); + return; + } + + try { + var data = JSON.parse($scanData.text()); + var jsonStr = JSON.stringify(data, null, 2); + var filename = 'wpcm-known-conflicts-' + WPCM_Admin.getDateString() + '.json'; + + WPCM_Admin.downloadFile(jsonStr, filename, 'application/json'); + WPCM_Admin.showNotice('Export completed successfully', 'success'); + } catch (err) { + WPCM_Admin.showNotice('Failed to export data: ' + err.message, 'error'); + } + }); + }, + + /** + * Get formatted date string for filenames + */ + getDateString: function() { + var now = new Date(); + var year = now.getFullYear(); + var month = String(now.getMonth() + 1).padStart(2, '0'); + var day = String(now.getDate()).padStart(2, '0'); + var hours = String(now.getHours()).padStart(2, '0'); + var minutes = String(now.getMinutes()).padStart(2, '0'); + return year + month + day + '-' + hours + minutes; } };