Plugin Directory

Changeset 3465229


Ignore:
Timestamp:
02/19/2026 04:32:36 PM (5 weeks ago)
Author:
redshape
Message:

1.3.0

Location:
redshape-easy-labels
Files:
16 edited
1 copied

Legend:

Unmodified
Added
Removed
  • redshape-easy-labels/tags/1.3.0/assets/css/admin-settings.css

    r3398988 r3465229  
    176176    margin-top: 4px;
    177177    display: block;
     178}
     179
     180.field-description-spaced {
     181    margin-top: 8px;
     182    color: #666;
     183}
     184
     185.field-description-indented {
     186    margin-left: 24px;
     187    display: block;
     188    color: #666;
     189}
     190
     191.field-description-with-bottom-gap {
     192    margin-bottom: 12px;
     193}
     194
     195.icon-accent {
     196    color: #2271b1;
     197}
     198
     199.icon-sm {
     200    font-size: 16px;
     201}
     202
     203.label-display-options {
     204    margin-top: 16px;
     205    padding-top: 16px;
     206    border-top: 1px solid #e5e5e5;
     207}
     208
     209.label-checkbox-option-spaced {
     210    margin-bottom: 12px;
     211}
     212
     213.default-label-row {
     214    display: flex;
     215    gap: 8px;
     216    align-items: flex-start;
     217}
     218
     219.default-label-row .label-name-input {
     220    flex: 1;
    178221}
    179222
     
    800843/* Reset button per default labels */
    801844.reset-default-label-btn {
     845    display: inline-flex;
     846    align-items: center;
     847    gap: 4px;
     848    padding: 8px 12px;
     849    background: #f0f0f1;
     850    border: 1px solid #c3c4c7;
     851    border-radius: 4px;
     852    cursor: pointer;
     853    font-size: 13px;
     854    color: #2c3338;
    802855    transition: all 0.2s ease;
    803856}
     
    816869
    817870.reset-default-label-btn .dashicons {
     871    font-size: 16px;
     872    width: 16px;
     873    height: 16px;
    818874    transition: transform 0.3s ease;
    819875}
     
    827883.border-style-options {
    828884    width: 100%;
     885}
     886
     887.border-style-options-grid {
     888    display: grid;
     889    grid-template-columns: repeat(5, 1fr);
     890    gap: 10px;
    829891}
    830892
     
    17201782    transition: all 0.2s ease;
    17211783}
     1784
     1785.hidden-file-input,
     1786.is-hidden {
     1787    display: none;
     1788}
     1789
     1790.widget-preview-badge {
     1791    display: inline-flex;
     1792    align-items: center;
     1793    gap: 8px;
     1794    padding: 8px 16px;
     1795    background: #2271b1;
     1796    color: #fff;
     1797    border-radius: 20px;
     1798    font-size: 14px;
     1799    font-weight: 500;
     1800    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
     1801    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
     1802}
     1803
     1804.widget-preview-badge .dashicons {
     1805    font-size: 16px;
     1806    width: 16px;
     1807    height: 16px;
     1808}
     1809
     1810.widget-two-col-grid {
     1811    display: grid;
     1812    grid-template-columns: 1fr 1fr;
     1813    gap: 15px;
     1814}
     1815
     1816.widget-bar-chart-options {
     1817    margin-top: 15px;
     1818}
     1819
     1820.widget-selected-labels-container {
     1821    margin-top: 15px;
     1822}
     1823
     1824.widget-selected-labels-title {
     1825    font-weight: 600;
     1826    margin-bottom: 10px;
     1827    color: #23282d;
     1828}
     1829
     1830.widget-selected-labels-title .dashicons {
     1831    font-size: 16px;
     1832    margin-right: 5px;
     1833}
     1834
     1835.widget-selected-labels-note {
     1836    font-weight: 400;
     1837    color: #666;
     1838    font-size: 12px;
     1839}
     1840
     1841.widget-selected-labels-list {
     1842    display: flex;
     1843    flex-wrap: wrap;
     1844    gap: 8px;
     1845    padding: 12px;
     1846    background: #f9f9f9;
     1847    border-radius: 4px;
     1848    min-height: 50px;
     1849}
     1850
     1851.widget-sortable-label {
     1852    cursor: move;
     1853    padding: 6px 12px;
     1854    color: #fff;
     1855    border-radius: 4px;
     1856    display: flex;
     1857    align-items: center;
     1858    gap: 6px;
     1859    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
     1860}
     1861
     1862.widget-sortable-label .dashicons {
     1863    font-size: 14px;
     1864}
     1865
     1866.system-info-section {
     1867    margin-bottom: 30px;
     1868}
     1869
     1870.system-info-title {
     1871    margin-bottom: 15px;
     1872    font-size: 18px;
     1873}
     1874
     1875.system-info-card {
     1876    background: #fff;
     1877    padding: 20px;
     1878    border: 1px solid #ddd;
     1879    border-radius: 8px;
     1880}
     1881
     1882.system-info-table {
     1883    border: none;
     1884}
     1885
     1886.system-info-label,
     1887.system-info-value {
     1888    padding: 10px;
     1889}
     1890
     1891.system-info-label {
     1892    font-weight: 600;
     1893}
     1894
     1895.system-info-section tbody tr:first-child .system-info-label {
     1896    width: 200px;
     1897}
     1898
     1899.system-info-row-alt {
     1900    background: #f9f9f9;
     1901}
     1902
     1903.system-info-path {
     1904    font-family: Monaco, Menlo, Ubuntu Mono, monospace;
     1905    font-size: 12px;
     1906}
     1907
     1908@media (max-width: 782px) {
     1909    .widget-two-col-grid {
     1910        grid-template-columns: 1fr;
     1911    }
     1912}
  • redshape-easy-labels/tags/1.3.0/assets/js/admin.js

    r3398988 r3465229  
    3131            // Global error handler
    3232            error: function(xhr, status, error) {
    33                 // Log for debugging
    34                 if (redshapeEasylabelsAjax.debug && window.console && console.error) {
    35                     console.error('Easy Labels AJAX Error:', {
    36                         status: status,
    37                         error: error,
    38                         responseText: xhr.responseText,
    39                         statusCode: xhr.status,
    40                         url: this.url,
    41                         data: this.data
    42                     });
    43                 }
    44                
    4533                // User-friendly message based on error type
    4634                let userMessage = __('Error occurred');
     
    9078        ajaxOptions.success = function(response, status, xhr) {
    9179            try {
    92                 // Basic response validation
    93                 if (redshapeEasylabelsAjax.debug && typeof response !== 'object') {
    94                     console.warn('Easy Labels: Response is not an object', response);
    95                 }
    96                
    9780                // Call original success handler
    9881                if (originalSuccess && typeof originalSuccess === 'function') {
     
    10083                }
    10184            } catch (e) {
    102                 // Catch errors in success handler
    103                 if (redshapeEasylabelsAjax.debug) {
    104                     console.error('Easy Labels: Error in success handler', e);
    105                 }
    10685                showMessage('Errore nell\'elaborazione della risposta', 'error');
    10786            }
     
    11291            return $.ajax(ajaxOptions);
    11392        } catch (e) {
    114             if (redshapeEasylabelsAjax.debug) {
    115                 console.error('Easy Labels: Exception in AJAX call', e);
    116             }
    11793            showMessage('Errore critico. Ricarica la pagina.', 'error');
    11894            return $.Deferred().reject(e);
    11995        }
    12096    }
    121    
    122     // First initialize global event listeners
    123     initializeLabelEvents();
    12497   
    12598    // Insert labels next to post titles
     
    229202    initializeLabelEvents();
    230203    initializeInlineLabels();
     204
     205    // Re-apply inline labels when list table is refreshed via AJAX
     206    $(document).on('redshapeEasylabels:tableUpdated', function() {
     207        initializeInlineLabels();
     208        setTimeout(function() {
     209            initializeDragAndDrop();
     210        }, 100);
     211    });
    231212   
    232213    // Initialize events for labels
     
    641622        return labels;
    642623    }
     624
     625    function ensurePostLabelsCache(postId) {
     626        if (typeof redshapeEasylabelsAjax === 'undefined') {
     627            return null;
     628        }
     629
     630        if (typeof redshapeEasylabelsAjax.post_labels === 'undefined' || redshapeEasylabelsAjax.post_labels === null) {
     631            redshapeEasylabelsAjax.post_labels = {};
     632        }
     633
     634        var cacheKey = postId.toString();
     635        if (!Array.isArray(redshapeEasylabelsAjax.post_labels[cacheKey])) {
     636            redshapeEasylabelsAjax.post_labels[cacheKey] = [];
     637        }
     638
     639        return redshapeEasylabelsAjax.post_labels[cacheKey];
     640    }
     641
     642    function syncPostLabelsCacheAdd(postId, labelId, labelName, labelColor) {
     643        var labelsCache = ensurePostLabelsCache(postId);
     644        if (!labelsCache) {
     645            return;
     646        }
     647
     648        var idString = labelId.toString();
     649        var exists = labelsCache.some(function(label) {
     650            return label && label.id && label.id.toString() === idString;
     651        });
     652
     653        if (!exists) {
     654            labelsCache.push({
     655                id: idString,
     656                name: labelName,
     657                color: labelColor
     658            });
     659        }
     660    }
     661
     662    function syncPostLabelsCacheRemove(postId, labelId) {
     663        var labelsCache = ensurePostLabelsCache(postId);
     664        if (!labelsCache) {
     665            return;
     666        }
     667
     668        var idString = labelId.toString();
     669        redshapeEasylabelsAjax.post_labels[postId.toString()] = labelsCache.filter(function(label) {
     670            return !(label && label.id && label.id.toString() === idString);
     671        });
     672    }
    643673   
    644674    // Function to add a label to post
     
    670700                    // AFTER: Sync with OTHER wrappers (not current)
    671701                    syncAddLabelToOtherVersions(postId, labelId, labelName, labelColor, wrapper);
     702
     703                    // Keep frontend cache in sync to avoid stale labels after AJAX list refresh
     704                    syncPostLabelsCacheAdd(postId, labelId, labelName, labelColor);
    672705                   
    673706                    // REINITIALIZE drag and drop for new elements
     
    718751                    // SYNCHRONIZATION: Remove label from BOTH versions (inline and column) for same post
    719752                    syncRemoveLabelFromAllVersions(postId, labelId);
     753
     754                    // Keep frontend cache in sync to avoid stale labels after AJAX list refresh
     755                    syncPostLabelsCacheRemove(postId, labelId);
    720756                   
    721757                    // IMPORTANT: Invalidate ALL dropdowns (including current one)
     
    903939                            var allName = allMatch[1];
    904940                            var hasCheckmark = allBadge.hasClass('current');
    905                             var checkmarkHtml = hasCheckmark ? '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
     941                            var checkmarkHtml = hasCheckmark ? '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
    906942                            allBadge.html(allName + ' (' + total + ')' + checkmarkHtml);
    907943                        }
     
    916952                            var noLabelName = noLabelMatch[1];
    917953                            var hasNoLabelCheckmark = noLabelBadge.hasClass('current');
    918                             var noLabelCheckmarkHtml = hasNoLabelCheckmark ? '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
     954                            var noLabelCheckmarkHtml = hasNoLabelCheckmark ? '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
    919955                            noLabelBadge.html(noLabelName + ' (' + counts.no_label.count + ')' + noLabelCheckmarkHtml);
    920956                        }
     
    956992                                // ✅ Preserve checkmark if filter is active
    957993                                var hasCheckmark = filterBadge.hasClass('current');
    958                                 var checkmarkHtml = hasCheckmark ? '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
     994                                var checkmarkHtml = hasCheckmark ? '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
    959995                                filterBadge.html(newText + checkmarkHtml);
    960996                            }
     
    18741910            '<div class="widget-editor-header">' +
    18751911                '<div class="widget-preview-large">' +
    1876                     '<span class="widget-preview-badge" style="display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; background: #2271b1; color: white; border-radius: 20px; font-size: 14px; font-weight: 500; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">' +
    1877                         '<span class="dashicons dashicons-chart-pie" style="font-size: 16px; width: 16px; height: 16px;"></span>' +
     1912                    '<span class="widget-preview-badge">' +
     1913                        '<span class="dashicons dashicons-chart-pie"></span>' +
    18781914                        '<span class="widget-preview-title">' + __('New Widget') + '</span>' +
    18791915                    '</span>' +
     
    18931929                '</div>' +
    18941930                '<div class="widget-field-row">' +
    1895                     '<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">' +
     1931                    '<div class="widget-two-col-grid">' +
    18961932                        '<div class="widget-field-group">' +
    18971933                            '<label class="widget-field-label">' + __('Content Type') + '</label>' +
     
    19121948                    '</div>' +
    19131949                '</div>' +
    1914                 '<div class="widget-bar-chart-options" data-widget-key="' + widgetKey + '" style="display: none; margin-top: 15px;">' +
    1915                     '<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">' +
     1950                '<div class="widget-bar-chart-options" data-widget-key="' + widgetKey + '" style="display: none;">' +
     1951                    '<div class="widget-two-col-grid">' +
    19161952                        '<div class="widget-field-group">' +
    19171953                            '<label class="widget-field-label">' + __('Orientation') + '</label>' +
     
    19391975                        labelsHtml +
    19401976                    '</div>' +
    1941                     '<div class="widget-selected-labels-container" style="margin-top: 15px; display: none;">' +
    1942                         '<div style="font-weight: 600; margin-bottom: 10px; color: #23282d;">' +
    1943                             '<span class="dashicons dashicons-sort" style="font-size: 16px; margin-right: 5px;"></span>' +
    1944                             __('Labels Order') + ' <span style="font-weight: normal; color: #666; font-size: 12px;">(' + __('Drag to reorder') + ')</span>' +
     1977                    '<div class="widget-selected-labels-container" style="display: none;">' +
     1978                        '<div class="widget-selected-labels-title">' +
     1979                            '<span class="dashicons dashicons-sort"></span>' +
     1980                            __('Labels Order') + ' <span class="widget-selected-labels-note">(' + __('Drag to reorder') + ')</span>' +
    19451981                        '</div>' +
    1946                         '<div class="widget-selected-labels-list" data-widget-key="' + widgetKey + '" style="display: flex; flex-wrap: wrap; gap: 8px; padding: 12px; background: #f9f9f9; border-radius: 4px; min-height: 50px;">' +
     1982                        '<div class="widget-selected-labels-list" data-widget-key="' + widgetKey + '">' +
    19471983                        '</div>' +
    19481984                    '</div>' +
    1949                     '<small class="field-description" style="margin-top: 8px; color: #666;">' +
     1985                    '<small class="field-description field-description-spaced">' +
    19501986                        __('Select which labels to include in this widget. Check "All labels" to include all available labels.') +
    19511987                    '</small>' +
     
    20972133        if ($(this).is(':checked')) {
    20982134            // Add to sortable list
    2099             var $labelItem = $('<div class="widget-sortable-label" data-label-key="' + labelKey + '" style="cursor: move; padding: 6px 12px; background: ' + labelColor + '; color: #fff; border-radius: 4px; display: flex; align-items: center; gap: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">' +
    2100                 '<span class="dashicons dashicons-menu" style="font-size: 14px;"></span>' +
     2135            var $labelItem = $('<div class="widget-sortable-label" data-label-key="' + labelKey + '" style="background: ' + labelColor + ';">' +
     2136                '<span class="dashicons dashicons-menu"></span>' +
    21012137                labelName +
    21022138                '<input type="hidden" name="widgets[' + widgetKey + '][label_order][]" value="' + labelKey + '">' +
  • redshape-easy-labels/tags/1.3.0/includes/admin-page.php

    r3398988 r3465229  
    357357                                ?>
    358358                            </div>
    359                             <small class="field-description" style="margin-top: 8px; color: #666;">
     359                            <small class="field-description field-description-spaced">
    360360                                <?php redshape_easylabels_cl_e('If no type is selected, the label will be visible on all enabled content types.'); ?>
    361361                            </small>
     
    363363                       
    364364                        <!-- NUOVO: Opzioni di visualizzazione nei filtri -->
    365                         <div class="label-display-options" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid #e5e5e5;">
     365                        <div class="label-display-options">
    366366                            <!-- Checkbox Percentuale -->
    367                             <label class="label-checkbox-option" style="margin-bottom: 12px;">
     367                            <label class="label-checkbox-option label-checkbox-option-spaced">
    368368                                <input type="checkbox"
    369369                                       name="labels[<?php echo esc_attr($redshape_easylabels_key); ?>][show_percentage]"
     
    371371                                       <?php checked(!empty($redshape_easylabels_label['show_percentage'])); ?> />
    372372                                <span class="checkbox-label">
    373                                     <span class="dashicons dashicons-chart-pie" style="color: #2271b1;"></span>
     373                                    <span class="dashicons dashicons-chart-pie icon-accent"></span>
    374374                                    <strong><?php redshape_easylabels_cl_e('Show percentage in filters'); ?></strong>
    375375                                </span>
    376376                            </label>
    377                             <small class="field-description" style="margin-left: 24px; display: block; margin-bottom: 12px; color: #666;">
     377                            <small class="field-description field-description-indented field-description-with-bottom-gap">
    378378                                <?php redshape_easylabels_cl_e('Display percentage (2 decimals) relative to total posts next to count'); ?>
    379379                            </small>
     
    386386                                       <?php checked(!empty($redshape_easylabels_label['show_fraction'])); ?> />
    387387                                <span class="checkbox-label">
    388                                     <span class="dashicons dashicons-editor-justify" style="color: #2271b1;"></span>
     388                                    <span class="dashicons dashicons-editor-justify icon-accent"></span>
    389389                                    <strong><?php redshape_easylabels_cl_e('Show fraction format (e.g.: 3/5)'); ?></strong>
    390390                                </span>
    391391                            </label>
    392                             <small class="field-description" style="margin-left: 24px; display: block; margin-top: 4px; color: #666;">
     392                            <small class="field-description field-description-indented">
    393393                                <?php redshape_easylabels_cl_e('Display count as fraction relative to total posts (e.g.: 3/5 instead of just 3)'); ?>
    394394                            </small>
     
    504504                            <div class="label-field-group flex-grow">
    505505                                <label class="label-field-label"><?php redshape_easylabels_cl_e('Label name'); ?></label>
    506                                 <div style="display: flex; gap: 8px; align-items: flex-start;">
     506                                    <div class="default-label-row">
    507507                                    <input type="text"
    508508                                           name="default_labels[all][name]"
     
    510510                                           class="label-name-input all-label-input"
    511511                                           placeholder="<?php redshape_easylabels_cl_e('e.g. All, Everything, View All'); ?>"
    512                                            style="flex: 1;" />
     512                                         />
    513513                                    <button type="button"
    514514                                            class="reset-default-label-btn"
     
    519519                                            data-default-border-color="#2271b1"
    520520                                            data-default-enabled="1"
    521                                             title="<?php redshape_easylabels_cl_e('Reset to default'); ?>"
    522                                             style="padding: 8px 12px; background: #f0f0f1; border: 1px solid #c3c4c7; border-radius: 4px; cursor: pointer; display: flex; align-items: center; gap: 4px; font-size: 13px; color: #2c3338; transition: all 0.2s;">
    523                                         <span class="dashicons dashicons-image-rotate" style="font-size: 16px; width: 16px; height: 16px;"></span>
     521                                            title="<?php redshape_easylabels_cl_e('Reset to default'); ?>">
     522                                        <span class="dashicons dashicons-image-rotate"></span>
    524523                                        <?php redshape_easylabels_cl_e('Reset'); ?>
    525524                                    </button>
     
    542541                        <div class="label-field-group">
    543542                            <label class="label-field-label">
    544                                 <span class="dashicons dashicons-admin-customizer" style="color: #2271b1; font-size: 16px;"></span>
     543                                <span class="dashicons dashicons-admin-customizer icon-accent icon-sm"></span>
    545544                                <?php redshape_easylabels_cl_e('Border Style'); ?>
    546545                            </label>
    547                             <div class="border-style-options" style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;">
     546                            <div class="border-style-options border-style-options-grid">
    548547                                <?php
    549548                                $redshape_easylabels_current_all_border_style = !empty($redshape_easylabels_default_label_settings['all']['border_style']) ? $redshape_easylabels_default_label_settings['all']['border_style'] : 'none';
     
    574573                        <div class="label-field-group all-border-color-field" style="<?php echo empty($redshape_easylabels_default_label_settings['all']['border_style']) || $redshape_easylabels_default_label_settings['all']['border_style'] === 'none' ? 'display: none;' : ''; ?>">
    575574                            <label class="label-field-label">
    576                                 <span class="dashicons dashicons-art" style="color: #2271b1; font-size: 16px;"></span>
     575                                <span class="dashicons dashicons-art icon-accent icon-sm"></span>
    577576                                <?php redshape_easylabels_cl_e('Border Color'); ?>
    578577                            </label>
     
    625624                            <div class="label-field-group flex-grow">
    626625                                <label class="label-field-label"><?php redshape_easylabels_cl_e('Label name'); ?></label>
    627                                 <div style="display: flex; gap: 8px; align-items: flex-start;">
     626                                    <div class="default-label-row">
    628627                                    <input type="text"
    629628                                           name="default_labels[none][name]"
     
    631630                                           class="label-name-input none-label-input"
    632631                                           placeholder="<?php redshape_easylabels_cl_e('e.g. No Label, Unlabeled, Without Labels'); ?>"
    633                                            style="flex: 1;" />
     632                                         />
    634633                                    <button type="button"
    635634                                            class="reset-default-label-btn"
     
    640639                                            data-default-border-color="#646970"
    641640                                            data-default-enabled="1"
    642                                             title="<?php redshape_easylabels_cl_e('Reset to default'); ?>"
    643                                             style="padding: 8px 12px; background: #f0f0f1; border: 1px solid #c3c4c7; border-radius: 4px; cursor: pointer; display: flex; align-items: center; gap: 4px; font-size: 13px; color: #2c3338; transition: all 0.2s;">
    644                                         <span class="dashicons dashicons-image-rotate" style="font-size: 16px; width: 16px; height: 16px;"></span>
     641                                            title="<?php redshape_easylabels_cl_e('Reset to default'); ?>">
     642                                        <span class="dashicons dashicons-image-rotate"></span>
    645643                                        <?php redshape_easylabels_cl_e('Reset'); ?>
    646644                                    </button>
     
    663661                        <div class="label-field-group">
    664662                            <label class="label-field-label">
    665                                 <span class="dashicons dashicons-admin-customizer" style="color: #2271b1; font-size: 16px;"></span>
     663                                <span class="dashicons dashicons-admin-customizer icon-accent icon-sm"></span>
    666664                                <?php redshape_easylabels_cl_e('Border Style'); ?>
    667665                            </label>
    668                             <div class="border-style-options" style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;">
     666                            <div class="border-style-options border-style-options-grid">
    669667                                <?php
    670668                                $redshape_easylabels_current_border_style = !empty($redshape_easylabels_default_label_settings['none']['border_style']) ? $redshape_easylabels_default_label_settings['none']['border_style'] : 'none';
     
    695693                        <div class="label-field-group none-border-color-field" style="<?php echo empty($redshape_easylabels_default_label_settings['none']['border_style']) || $redshape_easylabels_default_label_settings['none']['border_style'] === 'none' ? 'display: none;' : ''; ?>">
    696694                            <label class="label-field-label">
    697                                 <span class="dashicons dashicons-art" style="color: #2271b1; font-size: 16px;"></span>
     695                                <span class="dashicons dashicons-art icon-accent icon-sm"></span>
    698696                                <?php redshape_easylabels_cl_e('Border Color'); ?>
    699697                            </label>
     
    10561054                <div class="backup-actions">
    10571055                    <div class="file-upload-wrapper">
    1058                         <input type="file" id="import-file" accept=".json" style="display: none;" />
     1056                        <input type="file" id="import-file" accept=".json" class="hidden-file-input" />
    10591057                        <button type="button" id="select-import-file" class="button button-secondary button-hero">
    10601058                            <span class="dashicons dashicons-media-default"></span>
     
    10641062                    </div>
    10651063                   
    1066                     <button type="button" id="import-settings" class="button button-primary button-hero" style="display: none;">
     1064                    <button type="button" id="import-settings" class="button button-primary button-hero is-hidden">
    10671065                        <span class="dashicons dashicons-upload"></span>
    10681066                        <span><?php redshape_easylabels_cl_e('Import Settings'); ?></span>
     
    11101108                    <div class="widget-editor-header">
    11111109                        <div class="widget-preview-large">
    1112                             <span class="widget-preview-badge" style="display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; background: #2271b1; color: white; border-radius: 20px; font-size: 14px; font-weight: 500; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
    1113                                 <span class="dashicons dashicons-chart-pie" style="font-size: 16px; width: 16px; height: 16px;"></span>
     1110                            <span class="widget-preview-badge">
     1111                                <span class="dashicons dashicons-chart-pie"></span>
    11141112                                <span class="widget-preview-title"><?php echo esc_html($redshape_easylabels_widget['title']); ?></span>
    11151113                            </span>
     
    11331131                       
    11341132                        <div class="widget-field-row">
    1135                             <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
     1133                            <div class="widget-two-col-grid">
    11361134                                <div class="widget-field-group">
    11371135                                    <label class="widget-field-label"><?php redshape_easylabels_cl_e('Content Type'); ?></label>
     
    11591157                           
    11601158                            <!-- Bar Chart Options -->
    1161                             <div class="widget-bar-chart-options" data-widget-key="<?php echo esc_attr($redshape_easylabels_widget_key); ?>" style="display: <?php echo ($redshape_easylabels_widget['visualization_type'] === 'bar_chart') ? 'block' : 'none'; ?>; margin-top: 15px;">
    1162                                 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
     1159                            <div class="widget-bar-chart-options" data-widget-key="<?php echo esc_attr($redshape_easylabels_widget_key); ?>" style="display: <?php echo ($redshape_easylabels_widget['visualization_type'] === 'bar_chart') ? 'block' : 'none'; ?>;">
     1160                                <div class="widget-two-col-grid">
    11631161                                    <div class="widget-field-group">
    11641162                                        <label class="widget-field-label"><?php redshape_easylabels_cl_e('Orientation'); ?></label>
     
    12531251                           
    12541252                            <!-- Selected Labels Sortable List -->
    1255                             <div class="widget-selected-labels-container" style="margin-top: 15px; display: <?php echo (!empty($redshape_easylabels_labels_for_sortable) && !$redshape_easylabels_all_labels_checked) ? 'block' : 'none'; ?>;">
    1256                                 <div style="font-weight: 600; margin-bottom: 10px; color: #23282d;">
    1257                                     <span class="dashicons dashicons-sort" style="font-size: 16px; margin-right: 5px;"></span>
    1258                                     <?php redshape_easylabels_cl_e('Labels Order'); ?> <span style="font-weight: normal; color: #666; font-size: 12px;">(<?php redshape_easylabels_cl_e('Drag to reorder'); ?>)</span>
    1259                                 </div>
    1260                                 <div class="widget-selected-labels-list" data-widget-key="<?php echo esc_attr($redshape_easylabels_widget_key); ?>" style="display: flex; flex-wrap: wrap; gap: 8px; padding: 12px; background: #f9f9f9; border-radius: 4px; min-height: 50px;">
     1253                            <div class="widget-selected-labels-container" style="display: <?php echo (!empty($redshape_easylabels_labels_for_sortable) && !$redshape_easylabels_all_labels_checked) ? 'block' : 'none'; ?>;">
     1254                                <div class="widget-selected-labels-title">
     1255                                    <span class="dashicons dashicons-sort"></span>
     1256                                    <?php redshape_easylabels_cl_e('Labels Order'); ?> <span class="widget-selected-labels-note">(<?php redshape_easylabels_cl_e('Drag to reorder'); ?>)</span>
     1257                                </div>
     1258                                <div class="widget-selected-labels-list" data-widget-key="<?php echo esc_attr($redshape_easylabels_widget_key); ?>">
    12611259                                    <?php foreach ($redshape_easylabels_labels_for_sortable as $redshape_easylabels_selected_key):
    12621260                                        if ($redshape_easylabels_selected_key === '__no_label__'):
     
    12651263                                            $redshape_easylabels_label_color = $redshape_easylabels_no_label_color;
    12661264                                    ?>
    1267                                     <div class="widget-sortable-label" data-label-key="__no_label__" style="cursor: move; padding: 6px 12px; background: <?php echo esc_attr($redshape_easylabels_label_color); ?>; color: #fff; border-radius: 4px; display: flex; align-items: center; gap: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
    1268                                         <span class="dashicons dashicons-menu" style="font-size: 14px;"></span>
     1265                                    <div class="widget-sortable-label" data-label-key="__no_label__" style="background: <?php echo esc_attr($redshape_easylabels_label_color); ?>;">
     1266                                        <span class="dashicons dashicons-menu"></span>
    12691267                                        <?php echo esc_html($redshape_easylabels_label_name); ?>
    12701268                                        <input type="hidden" name="widgets[<?php echo esc_attr($redshape_easylabels_widget_key); ?>][label_order][]" value="__no_label__">
     
    12741272                                            $redshape_easylabels_label = $redshape_easylabels_labels[$redshape_easylabels_selected_key];
    12751273                                    ?>
    1276                                     <div class="widget-sortable-label" data-label-key="<?php echo esc_attr($redshape_easylabels_selected_key); ?>" style="cursor: move; padding: 6px 12px; background: <?php echo esc_attr($redshape_easylabels_label['color']); ?>; color: #fff; border-radius: 4px; display: flex; align-items: center; gap: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
    1277                                         <span class="dashicons dashicons-menu" style="font-size: 14px;"></span>
     1274                                    <div class="widget-sortable-label" data-label-key="<?php echo esc_attr($redshape_easylabels_selected_key); ?>" style="background: <?php echo esc_attr($redshape_easylabels_label['color']); ?>;">
     1275                                        <span class="dashicons dashicons-menu"></span>
    12781276                                        <?php echo esc_html($redshape_easylabels_label['name']); ?>
    12791277                                        <input type="hidden" name="widgets[<?php echo esc_attr($redshape_easylabels_widget_key); ?>][label_order][]" value="<?php echo esc_attr($redshape_easylabels_selected_key); ?>">
     
    12841282                                </div>
    12851283                            </div>
    1286                             <small class="field-description" style="margin-top: 8px; color: #666;">
     1284                            <small class="field-description field-description-spaced">
    12871285                                <?php redshape_easylabels_cl_e('Select which labels to include in this widget. Check "All labels" to include all available labels.'); ?>
    12881286                            </small>
     
    13221320       
    13231321        <!-- Plugin Information -->
    1324         <div class="system-info-section" style="margin-bottom: 30px;">
    1325             <h3 style="margin-bottom: 15px; font-size: 18px;"><?php redshape_easylabels_cl_e('Plugin Information'); ?></h3>
    1326             <div style="background: white; padding: 20px; border: 1px solid #ddd; border-radius: 8px;">
    1327                 <table class="widefat" style="border: none;">
     1322        <div class="system-info-section">
     1323            <h3 class="system-info-title"><?php redshape_easylabels_cl_e('Plugin Information'); ?></h3>
     1324            <div class="system-info-card">
     1325                <table class="widefat system-info-table">
    13281326                    <tbody>
    13291327                        <tr>
    1330                             <td style="padding: 10px; font-weight: 600; width: 200px;"><?php redshape_easylabels_cl_e('Plugin Version'); ?></td>
    1331                             <td style="padding: 10px;"><?php echo esc_html(REDSHAPE_EASYLABELS_VERSION); ?></td>
     1328                            <td class="system-info-label"><?php redshape_easylabels_cl_e('Plugin Version'); ?></td>
     1329                            <td class="system-info-value"><?php echo esc_html(REDSHAPE_EASYLABELS_VERSION); ?></td>
    13321330                        </tr>
    1333                         <tr style="background: #f9f9f9;">
    1334                             <td style="padding: 10px; font-weight: 600;"><?php redshape_easylabels_cl_e('WordPress Version'); ?></td>
    1335                             <td style="padding: 10px;"><?php echo esc_html(get_bloginfo('version')); ?></td>
     1331                        <tr class="system-info-row-alt">
     1332                            <td class="system-info-label"><?php redshape_easylabels_cl_e('WordPress Version'); ?></td>
     1333                            <td class="system-info-value"><?php echo esc_html(get_bloginfo('version')); ?></td>
    13361334                        </tr>
    13371335                        <tr>
    1338                             <td style="padding: 10px; font-weight: 600;"><?php redshape_easylabels_cl_e('PHP Version'); ?></td>
    1339                             <td style="padding: 10px;"><?php echo esc_html(phpversion()); ?></td>
     1336                            <td class="system-info-label"><?php redshape_easylabels_cl_e('PHP Version'); ?></td>
     1337                            <td class="system-info-value"><?php echo esc_html(phpversion()); ?></td>
    13401338                        </tr>
    1341                         <tr style="background: #f9f9f9;">
    1342                             <td style="padding: 10px; font-weight: 600;"><?php redshape_easylabels_cl_e('Plugin Path'); ?></td>
    1343                             <td style="padding: 10px; font-family: monospace; font-size: 12px;"><?php echo esc_html(REDSHAPE_EASYLABELS_PLUGIN_PATH); ?></td>
     1339                        <tr class="system-info-row-alt">
     1340                            <td class="system-info-label"><?php redshape_easylabels_cl_e('Plugin Path'); ?></td>
     1341                            <td class="system-info-value system-info-path"><?php echo esc_html(REDSHAPE_EASYLABELS_PLUGIN_PATH); ?></td>
    13441342                        </tr>
    13451343                    </tbody>
  • redshape-easy-labels/tags/1.3.0/includes/class-redshape-easylabels-cache.php

    r3397460 r3465229  
    3333     */
    3434    const CACHE_DURATION = 3600;
     35
     36    /**
     37     * Ottiene i post types abilitati dalle opzioni plugin con fallback retrocompatibile.
     38     *
     39     * @return array
     40     */
     41    private static function get_enabled_post_types() {
     42        $options = get_option('redshape_easylabels_options', array());
     43
     44        if (!empty($options['role_settings']['enabled_post_types']) && is_array($options['role_settings']['enabled_post_types'])) {
     45            return array_values($options['role_settings']['enabled_post_types']);
     46        }
     47
     48        // Backward compatibility con vecchia struttura opzioni.
     49        if (!empty($options['enabled_post_types']) && is_array($options['enabled_post_types'])) {
     50            return array_values($options['enabled_post_types']);
     51        }
     52
     53        return array('post', 'page');
     54    }
    3555   
    3656    /**
     
    6888    public static function invalidate_label($label_id) {
    6989        // Ottieni tutti i post types abilitati
    70         $options = get_option('redshape_easylabels_options', array());
    71         $enabled_post_types = isset($options['enabled_post_types']) ? $options['enabled_post_types'] : array('post');
     90        $enabled_post_types = self::get_enabled_post_types();
    7291       
    7392        $deleted_count = 0;
     
    152171        // Se nessun post type specificato, usa quelli abilitati nelle opzioni
    153172        if (empty($post_types)) {
    154             $options = get_option('redshape_easylabels_options', array());
    155             $post_types = isset($options['enabled_post_types']) ? $options['enabled_post_types'] : array('post');
     173            $post_types = self::get_enabled_post_types();
    156174        }
    157175       
  • redshape-easy-labels/tags/1.3.0/includes/class-redshape-easylabels.php

    r3398988 r3465229  
    4141        add_action('wp_ajax_redshape_easylabels_save_filter_order', array($this, 'ajax_save_filter_order'));
    4242        add_action('wp_ajax_redshape_easylabels_get_filter_counts', array($this, 'ajax_get_filter_counts')); // NEW: Filter counts
    43         add_action('wp_ajax_redshape_easylabels_debug_post_types', array($this, 'ajax_debug_post_types'));
    4443        add_action('wp_ajax_redshape_easylabels_export_settings', array($this, 'ajax_export_settings')); // NEW: Export
    4544        add_action('wp_ajax_redshape_easylabels_import_settings', array($this, 'ajax_import_settings')); // NEW: Import
     
    5857   
    5958    private $columns_rendered = array(); // Flag to avoid double rendering
    60     private $columns_added = array(); // Flag to avoid double column addition per post type
    6159   
    6260    // Universal system - register hooks for ALL post types and check dynamically
     
    9492    // Reset flags when screen changes
    9593    public function reset_column_flags() {
    96         $this->columns_added = array();
    9794        $this->columns_rendered = array();
    9895    }
     
    242239            // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
    243240            $filter_value = sanitize_text_field(wp_unslash($_GET['content_label_filter']));
     241
     242            // Read relation for multi-filter mode (default: AND)
     243            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter parameter, no data modification
     244            $filter_relation = isset($_GET['content_label_relation']) ? strtolower(sanitize_text_field(wp_unslash($_GET['content_label_relation']))) : 'and';
     245            if (!in_array($filter_relation, array('and', 'or'), true)) {
     246                $filter_relation = 'and';
     247            }
    244248           
    245249            // Check if multiple filters (comma-separated)
    246             $filter_values = array_map('trim', explode(',', $filter_value));
     250            $filter_values = array_filter(array_map('trim', explode(',', $filter_value)));
    247251            $has_multiple = count($filter_values) > 1;
    248252           
     
    253257           
    254258            if ($has_multiple) {
    255                 // Multiple filters with AND relation
    256                 $sub_queries = array('relation' => 'AND');
     259                // Multiple filters with configurable relation (AND/OR)
     260                $sub_queries = array('relation' => strtoupper($filter_relation));
    257261               
    258262                foreach ($filter_values as $single_filter) {
     
    339343        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter parameter, no data modification
    340344        $current_filter = isset($_GET['content_label_filter']) ? sanitize_text_field(wp_unslash($_GET['content_label_filter'])) : '';
    341         $base_url = remove_query_arg('content_label_filter');
     345        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter parameter, no data modification
     346        $current_filter_relation = isset($_GET['content_label_relation']) ? strtolower(sanitize_text_field(wp_unslash($_GET['content_label_relation']))) : 'and';
     347        if (!in_array($current_filter_relation, array('and', 'or'), true)) {
     348            $current_filter_relation = 'and';
     349        }
     350
     351        $base_url = remove_query_arg(array('content_label_filter', 'content_label_relation'));
    342352       
    343353        // NUOVO: Conta i post SENZA etichette e il totale (prima di generare l'HTML)
     
    435445            $all_badge_html .= esc_html($all_name) . ' (' . intval($total_posts_count) . ')';
    436446            if ($all_class === 'current') {
    437                 $all_badge_html .= '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
     447                $all_badge_html .= '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
    438448            }
    439449            $all_badge_html .= '</span>';
     
    463473            $no_label_badge_html .= esc_html($no_label_name) . ' (' . intval($no_label_count) . ')';
    464474            if ($no_label_class === 'current') {
    465                 $no_label_badge_html .= '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
     475                $no_label_badge_html .= '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
    466476            }
    467477            $no_label_badge_html .= '</span>';
     
    484494            $quick_filter_html .= '</div>';
    485495           
    486             // Pulsante "Applica" per multi-select (inizialmente nascosto)
    487             $quick_filter_html .= '<button type="button" class="multi-select-apply-btn" id="multi-apply-btn">' . esc_html(redshape_easylabels_cl__('Apply')) . '</button>';
    488            
    489             // Separatore verticale dopo Apply
     496            // Selettore relazione AND/OR per multi-select
     497            $quick_filter_html .= '<div class="filter-relation-toggle" id="filter-relation-toggle" data-default-relation="' . esc_attr($current_filter_relation) . '">';
     498            $quick_filter_html .= '<button type="button" class="relation-btn relation-btn-and" data-relation="and">AND</button>';
     499            $quick_filter_html .= '<button type="button" class="relation-btn relation-btn-or" data-relation="or">OR</button>';
     500            $quick_filter_html .= '</div>';
     501
     502            // Separatore verticale dopo selettore relazione
    490503            $quick_filter_html .= '<span style="width: 1px; height: 16px; background-color: #ddd; margin: 0 4px;"></span>';
    491504        }
     
    593606            $badge_html .= esc_html($label['name']) . ' ' . $count_display;
    594607            if ($is_active) {
    595                 $badge_html .= '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
     608                $badge_html .= '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
    596609            }
    597610            $badge_html .= '</span>';
     
    712725                'post_type_enabled' => $post_type_enabled, // NUOVO: flag per il JavaScript
    713726                'translations' => $translations, // NUOVO: Traduzioni per JavaScript
    714                 'debug' => defined('WP_DEBUG') && WP_DEBUG, // Debug mode flag
    715727                'no_label_name' => $no_label_name, // Nome personalizzato per No Label
    716728                'no_label_color' => $no_label_color // Colore personalizzato per No Label
     
    878890                        border: 1px solid white;
    879891                    }
    880                     .multi-select-apply-btn {
     892                    .filter-relation-toggle {
    881893                        display: none;
    882                         background-color: #2271b1;
    883                         color: white;
    884                         padding: 4px 12px;
     894                        align-items: center;
     895                        gap: 4px;
     896                        padding: 2px;
     897                        background: #f0f0f1;
    885898                        border-radius: 12px;
     899                    }
     900                    .filter-relation-toggle.visible {
     901                        display: inline-flex;
     902                    }
     903                    .relation-btn {
     904                        border: 1px solid #c3c4c7;
     905                        background: #fff;
     906                        color: #50575e;
     907                        padding: 2px 10px;
     908                        border-radius: 10px;
    886909                        font-size: 11px;
    887                         font-weight: 500;
    888                         cursor: grab;
    889                         transition: all 0.2s ease;
    890                         position: relative;
    891                         border: 4px solid #135e96;
    892                     }
    893                     .multi-select-apply-btn:hover {
    894                         transform: scale(1.05);
    895                         box-shadow: 0 2px 4px rgba(0,0,0,0.2);
    896                     }
    897                     .multi-select-apply-btn.visible {
    898                         display: inline-block;
     910                        line-height: 1.5;
     911                        cursor: pointer;
     912                    }
     913                    .relation-btn.active {
     914                        background: #2271b1;
     915                        border-color: #2271b1;
     916                        color: #fff;
    899917                    }
    900918                ';
     
    926944                    var isMultiMode = false;
    927945                    var selectedFilters = [];
    928                     var applyBtn = $("#multi-apply-btn");
    929                    
    930                     applyBtn.on("click", function(e) {
     946                    var filterRelation = "and";
     947                    var currentSingleFilter = "";
     948                    var relationToggle = $("#filter-relation-toggle");
     949
     950                    function normalizeFromParams(params) {
     951                        isMultiMode = params.get("multi_mode") === "1";
     952                        selectedFilters = (params.get("content_label_filter") || "").split(",").filter(function(v) { return v !== ""; });
     953                        filterRelation = params.get("content_label_relation") === "or" ? "or" : "and";
     954                        currentSingleFilter = !isMultiMode && selectedFilters.length > 0 ? selectedFilters[0] : "";
     955                    }
     956
     957                    function getCheckmarkHtml() {
     958                        return "<span class=\"filter-checkmark\" style=\"position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;\">✓</span>";
     959                    }
     960
     961                    function setCurrentBadge(labelId) {
     962                        var allBadges = $(".filter-badge, .filter-badge-fixed");
     963                        allBadges.removeClass("current");
     964                        allBadges.find(".filter-checkmark").remove();
     965
     966                        var selector = labelId === ""
     967                            ? ".filter-badge-fixed[data-label-id=\"\"]"
     968                            : ".filter-badge[data-label-id=\"" + labelId + "\"], .filter-badge-fixed[data-label-id=\"" + labelId + "\"]";
     969
     970                        var activeBadge = $(selector).first();
     971                        if (activeBadge.length > 0) {
     972                            activeBadge.addClass("current");
     973                            if (activeBadge.find(".filter-checkmark").length === 0) {
     974                                activeBadge.append(getCheckmarkHtml());
     975                            }
     976                        }
     977                    }
     978
     979                    function updateRelationUI() {
     980                        relationToggle = $("#filter-relation-toggle");
     981                        relationToggle.find(".relation-btn").removeClass("active");
     982                        relationToggle.find(".relation-btn[data-relation=\"" + filterRelation + "\"]").addClass("active");
     983                    }
     984
     985                    function repositionFilterBar() {
     986                        var currentFilterBar = $(".content-labels-quick-filter-bar");
     987                        if (currentFilterBar.length > 0) {
     988                            if (currentFilterBar.parent().is("a")) {
     989                                currentFilterBar.unwrap();
     990                            }
     991                            var topNav = $(".tablenav.top");
     992                            if (topNav.length > 0) {
     993                                currentFilterBar.detach().insertAfter(topNav);
     994                            }
     995                            currentFilterBar.css({
     996                                "display": "block",
     997                                "float": "none",
     998                                "clear": "both",
     999                                "width": "100%"
     1000                            });
     1001                        }
     1002                    }
     1003
     1004                    function applyFiltersAjax(params) {
     1005                        var query = params.toString();
     1006                        var targetUrl = window.location.pathname + (query ? "?" + query : "");
     1007
     1008                        $.ajax({
     1009                            url: targetUrl,
     1010                            type: "GET",
     1011                            success: function(responseHtml) {
     1012                                var responseDoc = $("<div>").html(responseHtml);
     1013                                var newListTable = responseDoc.find("#posts-filter .wp-list-table").first();
     1014                                var newTopNav = responseDoc.find("#posts-filter .tablenav.top").first();
     1015                                var newBottomNav = responseDoc.find("#posts-filter .tablenav.bottom").first();
     1016
     1017                                if (newListTable.length === 0) {
     1018                                    window.location.href = targetUrl;
     1019                                    return;
     1020                                }
     1021
     1022                                var currentListTable = $("#posts-filter .wp-list-table").first();
     1023                                if (currentListTable.length > 0) {
     1024                                    currentListTable.replaceWith(newListTable);
     1025                                } else {
     1026                                    window.location.href = targetUrl;
     1027                                    return;
     1028                                }
     1029
     1030                                var currentTopNav = $("#posts-filter .tablenav.top").first();
     1031                                if (currentTopNav.length > 0 && newTopNav.length > 0) {
     1032                                    currentTopNav.replaceWith(newTopNav);
     1033                                }
     1034
     1035                                var currentBottomNav = $("#posts-filter .tablenav.bottom").first();
     1036                                if (currentBottomNav.length > 0 && newBottomNav.length > 0) {
     1037                                    currentBottomNav.replaceWith(newBottomNav);
     1038                                }
     1039
     1040                                window.history.replaceState({}, "", targetUrl);
     1041
     1042                                var appliedParams = new URLSearchParams(query);
     1043                                normalizeFromParams(appliedParams);
     1044
     1045                                updateRelationUI();
     1046                                syncMultiVisualState();
     1047                                attachBadgeHandlers();
     1048                                $(document).trigger("redshapeEasylabels:tableUpdated");
     1049                            },
     1050                            error: function() {
     1051                                window.location.href = targetUrl;
     1052                            }
     1053                        });
     1054                    }
     1055
     1056                    function syncMultiVisualState() {
     1057                        if (isMultiMode) {
     1058                            $("#filter-mode-checkbox").prop("checked", true);
     1059                            $(".filter-mode-slider").css("background-color", "#46b450");
     1060                            $(".filter-badge-fixed[data-label-id=\"\"]").hide();
     1061                            $("#filter-relation-toggle").addClass("visible");
     1062                            $(".filter-badge, .filter-badge-fixed").removeClass("multi-selected current");
     1063                            $(".filter-badge, .filter-badge-fixed").find(".filter-checkmark").remove();
     1064
     1065                            selectedFilters.forEach(function(filterId) {
     1066                                $(".filter-badge[data-label-id=\"" + filterId + "\"], .filter-badge-fixed[data-label-id=\"" + filterId + "\"]").addClass("multi-selected");
     1067                            });
     1068                        } else {
     1069                            $("#filter-mode-checkbox").prop("checked", false);
     1070                            $(".filter-mode-slider").css("background-color", "#ccc");
     1071                            $(".filter-badge-fixed[data-label-id=\"\"]").show();
     1072                            $("#filter-relation-toggle").removeClass("visible");
     1073                            $(".filter-badge, .filter-badge-fixed").removeClass("multi-selected");
     1074                            setCurrentBadge(currentSingleFilter);
     1075                        }
     1076                    }
     1077
     1078                    relationToggle.find(".relation-btn").on("click", function(e) {
    9311079                        e.preventDefault();
    932                         if (selectedFilters.length > 0) {
    933                             var params = new URLSearchParams(window.location.search);
    934                             params.set("content_label_filter", selectedFilters.join(","));
    935                             window.location.href = window.location.pathname + "?" + params.toString();
     1080                        filterRelation = $(this).data("relation") === "or" ? "or" : "and";
     1081                        updateRelationUI();
     1082
     1083                        if (isMultiMode && selectedFilters.length > 0) {
     1084                            var relationParams = new URLSearchParams(window.location.search);
     1085                            relationParams.set("multi_mode", "1");
     1086                            relationParams.set("content_label_filter", selectedFilters.join(","));
     1087                            relationParams.set("content_label_relation", filterRelation);
     1088                            applyFiltersAjax(relationParams);
    9361089                        }
    9371090                    });
     
    9451098                           
    9461099                            if (labelId === "") {
    947                                 window.location.href = filterUrl;
     1100                                var allParams = new URLSearchParams(window.location.search);
     1101                                allParams.delete("content_label_filter");
     1102                                allParams.delete("content_label_relation");
     1103                                allParams.delete("multi_mode");
     1104                                applyFiltersAjax(allParams);
    9481105                                return false;
    9491106                            }
    9501107                           
    9511108                            if (!isMulti) {
    952                                 window.location.href = filterUrl;
     1109                                applyFiltersAjax(new URLSearchParams((filterUrl.split("?")[1] || "")));
    9531110                                return false;
    9541111                            } else {
     
    9651122                                    $(this).addClass("multi-selected");
    9661123                                }
     1124
     1125                                var multiParams = new URLSearchParams(window.location.search);
     1126                                multiParams.set("multi_mode", "1");
     1127                                multiParams.set("content_label_relation", filterRelation);
     1128
     1129                                if (selectedFilters.length > 0) {
     1130                                    multiParams.set("content_label_filter", selectedFilters.join(","));
     1131                                } else {
     1132                                    multiParams.delete("content_label_filter");
     1133                                }
     1134
     1135                                applyFiltersAjax(multiParams);
    9671136                               
    9681137                                return false;
     
    9751144                    // Check if multi-mode is active from URL
    9761145                    var params = new URLSearchParams(window.location.search);
    977                     if (params.get("multi_mode") === "1") {
    978                         $("#filter-mode-checkbox").prop("checked", true);
    979                         isMultiMode = true;
    980                         $(".filter-mode-slider").css("background-color", "#46b450");
    981                         $(".filter-badge-fixed[data-label-id=\'\']").hide();
    982                         applyBtn.addClass("visible");
    983                        
    984                         var activeFilters = params.get("content_label_filter");
    985                         if (activeFilters) {
    986                             selectedFilters = activeFilters.split(",");
    987                             selectedFilters.forEach(function(filterId) {
    988                                 $(".filter-badge[data-label-id=\'" + filterId + "\'], .filter-badge-fixed[data-label-id=\'" + filterId + "\']").addClass("multi-selected");
    989                             });
    990                         }
    991                     }
     1146                    normalizeFromParams(params);
     1147
     1148                    if (!params.get("content_label_relation") && relationToggle.data("default-relation") === "or") {
     1149                        filterRelation = "or";
     1150                    }
     1151
     1152                    updateRelationUI();
     1153                    syncMultiVisualState();
    9921154                   
    9931155                    // Toggle multi-select mode
    9941156                    $("#filter-mode-checkbox").on("change", function() {
     1157                        var hadActiveFilters = selectedFilters.length > 0;
    9951158                        isMultiMode = $(this).is(":checked");
    9961159                        selectedFilters = [];
    997                         $(".filter-badge, .filter-badge-fixed").removeClass("multi-selected");
     1160                        currentSingleFilter = "";
    9981161                       
    999                         var params = new URLSearchParams(window.location.search);
    1000                         params.delete("content_label_filter");
     1162                        var toggleParams = new URLSearchParams(window.location.search);
     1163                        toggleParams.delete("content_label_filter");
     1164                        toggleParams.delete("content_label_relation");
    10011165                       
    10021166                        if (isMultiMode) {
    1003                             params.set("multi_mode", "1");
     1167                            toggleParams.set("multi_mode", "1");
     1168                            toggleParams.set("content_label_relation", filterRelation);
    10041169                        } else {
    1005                             params.delete("multi_mode");
     1170                            toggleParams.delete("multi_mode");
    10061171                        }
    1007                        
    1008                         var newUrl = window.location.pathname + (params.toString() ? "?" + params.toString() : "");
    1009                         window.location.href = newUrl;
     1172
     1173                        if (hadActiveFilters) {
     1174                            applyFiltersAjax(toggleParams);
     1175                        } else {
     1176                            window.history.replaceState({}, "", window.location.pathname + (toggleParams.toString() ? "?" + toggleParams.toString() : ""));
     1177                            syncMultiVisualState();
     1178                            updateRelationUI();
     1179                        }
    10101180                    });
    10111181                });
     
    15031673            setTimeout(function() { newCardEl.removeClass('new-label'); }, 300);
    15041674            labelCounter++;
    1505         } catch(error) {
    1506             if (typeof redshapeEasylabelsAjax !== 'undefined' && redshapeEasylabelsAjax.debug) {
    1507                 console.error('Error adding label:', error);
    1508             }
     1675        } catch(_error) {
    15091676        }
    15101677    });
  • redshape-easy-labels/tags/1.3.0/readme.txt

    r3409971 r3465229  
    55Tested up to: 6.9
    66Requires PHP: 7.0
    7 Stable tag: 1.2.0
     7Stable tag: 1.3.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    7777= How does multi-select filtering work? =
    7878
    79 Toggle the Multi switch in the quick filters to enable multi-select mode. Click multiple label badges to select them (they'll show a green checkmark), then click Apply to filter posts that have ALL the selected labels together. The filter uses AND logic, so only posts with every selected label will be shown.
     79Toggle the Multi switch in the quick filters to enable multi-select mode. Click label badges to apply filters immediately (AJAX) without page reload, and choose AND or OR mode. AND returns posts that match all selected labels, while OR returns posts that match at least one selected label.
    8080
    8181== Screenshots ==
     
    9393
    9494== Changelog ==
     95
     96= 1.3.0 =
     97* Maintenance: Version bump to 1.3.0
     98* Compatibility: Tested up to WordPress 6.9
     99* New: Multi-select filters now support AND/OR relation modes
     100* Enhancement: Quick filters now apply instantly via AJAX (no Apply button)
     101* Fix: Removed duplicated uninstall cleanup blocks (cache/meta/transient)
     102* Fix: Aligned cache post type source with role_settings[enabled_post_types] and backward-compatible fallback
     103* Fix: Removed duplicate initializeLabelEvents() call in admin JavaScript
    95104
    96105= 1.2.0 =
     
    178187== Upgrade Notice ==
    179188
     189= 1.3.0 =
     190Maintenance release: metadata update (tested up to 6.9), AND/OR multi-select filtering support, and technical cleanup for uninstall, cache option consistency, and admin JS initialization.
     191
    180192= 1.2.0 =
    181193Major feature update: Adds dashboard widgets with 5 visualization types and interactive click-to-filter functionality. Includes drag & drop label ordering for complete customization.
  • redshape-easy-labels/tags/1.3.0/redshape-easy-labels.php

    r3398988 r3465229  
    33 * Plugin Name: REDSHAPE Easy Labels
    44 * Description: Colored labels and internal notes system for posts and pages, visible only in backend for content organization. Supports 10 languages (IT, EN, FR, DE, ES, RU, ZH, JA, KO, HI).
    5  * Version: 1.2.0
     5 * Version: 1.3.0
    66 * Author: REDSHAPE
    77 * Author URI: https://redshape.it
     
    1818
    1919// Define plugin constants
    20 define('REDSHAPE_EASYLABELS_VERSION', '1.2.0');
     20define('REDSHAPE_EASYLABELS_VERSION', '1.3.0');
    2121define('REDSHAPE_EASYLABELS_PLUGIN_URL', plugin_dir_url(__FILE__));
    2222define('REDSHAPE_EASYLABELS_PLUGIN_PATH', plugin_dir_path(__FILE__));
     
    4848    function redshape_easylabels_cl_e($string) {
    4949        echo esc_html(Redshape_Easylabels_I18n::__($string));
    50     }
    51 }
    52 
    53 /**
    54  * Helper function for plugin logging
    55  * Only logs if WP_DEBUG is enabled to avoid production logging
    56  * Uses WordPress logging system to avoid direct error_log usage
    57  *
    58  * @param string $message The message to log
    59  */
    60 if (!function_exists('redshape_easylabels_log')) {
    61     function redshape_easylabels_log($message) {
    62         // Only log in debug mode to avoid production logging
    63         if (defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
    64             // Use WordPress debug system - writes to wp-content/debug.log
    65             $log_message = 'REDSHAPE Easy Labels: ' . $message;
    66            
    67             // Use WordPress logging system - only wp_debug_log to avoid filesystem issues
    68             if (function_exists('wp_debug_log')) {
    69                 wp_debug_log($log_message);
    70             }
    71             // If wp_debug_log is not available, silently skip logging to avoid warnings
    72         }
    7350    }
    7451}
  • redshape-easy-labels/tags/1.3.0/uninstall.php

    r3397353 r3465229  
    5454// 6. CLEANUP TRANSIENTS (if any remain)
    5555delete_transient('redshape_easylabels_version_check');
    56 
    57 // 3. RIMUOVI CACHE (se presente)
    58 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    59 $wpdb->query(
    60     "DELETE FROM {$wpdb->options}
    61      WHERE option_name LIKE 'redshape_easylabels_counts_%'"
    62 );
    63 
    64 // 4. RIMUOVI TUTTI I META DATI DELLE ETICHETTE
    65 // Meta key: _content_labels (array di etichette per ogni post)
    66 delete_post_meta_by_key('_content_labels');
    67 
    68 // 5. RIMUOVI TUTTI I META DATI DELLE NOTE
    69 // Meta key: _content_note (nota testuale per ogni post)
    70 delete_post_meta_by_key('_content_note');
    71 
    72 // 6. CLEANUP TRANSIENTS (if any remain)
    73 delete_transient('redshape_easylabels_version_check');
    7456// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    7557$wpdb->query(
  • redshape-easy-labels/trunk/assets/css/admin-settings.css

    r3398988 r3465229  
    176176    margin-top: 4px;
    177177    display: block;
     178}
     179
     180.field-description-spaced {
     181    margin-top: 8px;
     182    color: #666;
     183}
     184
     185.field-description-indented {
     186    margin-left: 24px;
     187    display: block;
     188    color: #666;
     189}
     190
     191.field-description-with-bottom-gap {
     192    margin-bottom: 12px;
     193}
     194
     195.icon-accent {
     196    color: #2271b1;
     197}
     198
     199.icon-sm {
     200    font-size: 16px;
     201}
     202
     203.label-display-options {
     204    margin-top: 16px;
     205    padding-top: 16px;
     206    border-top: 1px solid #e5e5e5;
     207}
     208
     209.label-checkbox-option-spaced {
     210    margin-bottom: 12px;
     211}
     212
     213.default-label-row {
     214    display: flex;
     215    gap: 8px;
     216    align-items: flex-start;
     217}
     218
     219.default-label-row .label-name-input {
     220    flex: 1;
    178221}
    179222
     
    800843/* Reset button per default labels */
    801844.reset-default-label-btn {
     845    display: inline-flex;
     846    align-items: center;
     847    gap: 4px;
     848    padding: 8px 12px;
     849    background: #f0f0f1;
     850    border: 1px solid #c3c4c7;
     851    border-radius: 4px;
     852    cursor: pointer;
     853    font-size: 13px;
     854    color: #2c3338;
    802855    transition: all 0.2s ease;
    803856}
     
    816869
    817870.reset-default-label-btn .dashicons {
     871    font-size: 16px;
     872    width: 16px;
     873    height: 16px;
    818874    transition: transform 0.3s ease;
    819875}
     
    827883.border-style-options {
    828884    width: 100%;
     885}
     886
     887.border-style-options-grid {
     888    display: grid;
     889    grid-template-columns: repeat(5, 1fr);
     890    gap: 10px;
    829891}
    830892
     
    17201782    transition: all 0.2s ease;
    17211783}
     1784
     1785.hidden-file-input,
     1786.is-hidden {
     1787    display: none;
     1788}
     1789
     1790.widget-preview-badge {
     1791    display: inline-flex;
     1792    align-items: center;
     1793    gap: 8px;
     1794    padding: 8px 16px;
     1795    background: #2271b1;
     1796    color: #fff;
     1797    border-radius: 20px;
     1798    font-size: 14px;
     1799    font-weight: 500;
     1800    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
     1801    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
     1802}
     1803
     1804.widget-preview-badge .dashicons {
     1805    font-size: 16px;
     1806    width: 16px;
     1807    height: 16px;
     1808}
     1809
     1810.widget-two-col-grid {
     1811    display: grid;
     1812    grid-template-columns: 1fr 1fr;
     1813    gap: 15px;
     1814}
     1815
     1816.widget-bar-chart-options {
     1817    margin-top: 15px;
     1818}
     1819
     1820.widget-selected-labels-container {
     1821    margin-top: 15px;
     1822}
     1823
     1824.widget-selected-labels-title {
     1825    font-weight: 600;
     1826    margin-bottom: 10px;
     1827    color: #23282d;
     1828}
     1829
     1830.widget-selected-labels-title .dashicons {
     1831    font-size: 16px;
     1832    margin-right: 5px;
     1833}
     1834
     1835.widget-selected-labels-note {
     1836    font-weight: 400;
     1837    color: #666;
     1838    font-size: 12px;
     1839}
     1840
     1841.widget-selected-labels-list {
     1842    display: flex;
     1843    flex-wrap: wrap;
     1844    gap: 8px;
     1845    padding: 12px;
     1846    background: #f9f9f9;
     1847    border-radius: 4px;
     1848    min-height: 50px;
     1849}
     1850
     1851.widget-sortable-label {
     1852    cursor: move;
     1853    padding: 6px 12px;
     1854    color: #fff;
     1855    border-radius: 4px;
     1856    display: flex;
     1857    align-items: center;
     1858    gap: 6px;
     1859    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
     1860}
     1861
     1862.widget-sortable-label .dashicons {
     1863    font-size: 14px;
     1864}
     1865
     1866.system-info-section {
     1867    margin-bottom: 30px;
     1868}
     1869
     1870.system-info-title {
     1871    margin-bottom: 15px;
     1872    font-size: 18px;
     1873}
     1874
     1875.system-info-card {
     1876    background: #fff;
     1877    padding: 20px;
     1878    border: 1px solid #ddd;
     1879    border-radius: 8px;
     1880}
     1881
     1882.system-info-table {
     1883    border: none;
     1884}
     1885
     1886.system-info-label,
     1887.system-info-value {
     1888    padding: 10px;
     1889}
     1890
     1891.system-info-label {
     1892    font-weight: 600;
     1893}
     1894
     1895.system-info-section tbody tr:first-child .system-info-label {
     1896    width: 200px;
     1897}
     1898
     1899.system-info-row-alt {
     1900    background: #f9f9f9;
     1901}
     1902
     1903.system-info-path {
     1904    font-family: Monaco, Menlo, Ubuntu Mono, monospace;
     1905    font-size: 12px;
     1906}
     1907
     1908@media (max-width: 782px) {
     1909    .widget-two-col-grid {
     1910        grid-template-columns: 1fr;
     1911    }
     1912}
  • redshape-easy-labels/trunk/assets/js/admin.js

    r3398988 r3465229  
    3131            // Global error handler
    3232            error: function(xhr, status, error) {
    33                 // Log for debugging
    34                 if (redshapeEasylabelsAjax.debug && window.console && console.error) {
    35                     console.error('Easy Labels AJAX Error:', {
    36                         status: status,
    37                         error: error,
    38                         responseText: xhr.responseText,
    39                         statusCode: xhr.status,
    40                         url: this.url,
    41                         data: this.data
    42                     });
    43                 }
    44                
    4533                // User-friendly message based on error type
    4634                let userMessage = __('Error occurred');
     
    9078        ajaxOptions.success = function(response, status, xhr) {
    9179            try {
    92                 // Basic response validation
    93                 if (redshapeEasylabelsAjax.debug && typeof response !== 'object') {
    94                     console.warn('Easy Labels: Response is not an object', response);
    95                 }
    96                
    9780                // Call original success handler
    9881                if (originalSuccess && typeof originalSuccess === 'function') {
     
    10083                }
    10184            } catch (e) {
    102                 // Catch errors in success handler
    103                 if (redshapeEasylabelsAjax.debug) {
    104                     console.error('Easy Labels: Error in success handler', e);
    105                 }
    10685                showMessage('Errore nell\'elaborazione della risposta', 'error');
    10786            }
     
    11291            return $.ajax(ajaxOptions);
    11392        } catch (e) {
    114             if (redshapeEasylabelsAjax.debug) {
    115                 console.error('Easy Labels: Exception in AJAX call', e);
    116             }
    11793            showMessage('Errore critico. Ricarica la pagina.', 'error');
    11894            return $.Deferred().reject(e);
    11995        }
    12096    }
    121    
    122     // First initialize global event listeners
    123     initializeLabelEvents();
    12497   
    12598    // Insert labels next to post titles
     
    229202    initializeLabelEvents();
    230203    initializeInlineLabels();
     204
     205    // Re-apply inline labels when list table is refreshed via AJAX
     206    $(document).on('redshapeEasylabels:tableUpdated', function() {
     207        initializeInlineLabels();
     208        setTimeout(function() {
     209            initializeDragAndDrop();
     210        }, 100);
     211    });
    231212   
    232213    // Initialize events for labels
     
    641622        return labels;
    642623    }
     624
     625    function ensurePostLabelsCache(postId) {
     626        if (typeof redshapeEasylabelsAjax === 'undefined') {
     627            return null;
     628        }
     629
     630        if (typeof redshapeEasylabelsAjax.post_labels === 'undefined' || redshapeEasylabelsAjax.post_labels === null) {
     631            redshapeEasylabelsAjax.post_labels = {};
     632        }
     633
     634        var cacheKey = postId.toString();
     635        if (!Array.isArray(redshapeEasylabelsAjax.post_labels[cacheKey])) {
     636            redshapeEasylabelsAjax.post_labels[cacheKey] = [];
     637        }
     638
     639        return redshapeEasylabelsAjax.post_labels[cacheKey];
     640    }
     641
     642    function syncPostLabelsCacheAdd(postId, labelId, labelName, labelColor) {
     643        var labelsCache = ensurePostLabelsCache(postId);
     644        if (!labelsCache) {
     645            return;
     646        }
     647
     648        var idString = labelId.toString();
     649        var exists = labelsCache.some(function(label) {
     650            return label && label.id && label.id.toString() === idString;
     651        });
     652
     653        if (!exists) {
     654            labelsCache.push({
     655                id: idString,
     656                name: labelName,
     657                color: labelColor
     658            });
     659        }
     660    }
     661
     662    function syncPostLabelsCacheRemove(postId, labelId) {
     663        var labelsCache = ensurePostLabelsCache(postId);
     664        if (!labelsCache) {
     665            return;
     666        }
     667
     668        var idString = labelId.toString();
     669        redshapeEasylabelsAjax.post_labels[postId.toString()] = labelsCache.filter(function(label) {
     670            return !(label && label.id && label.id.toString() === idString);
     671        });
     672    }
    643673   
    644674    // Function to add a label to post
     
    670700                    // AFTER: Sync with OTHER wrappers (not current)
    671701                    syncAddLabelToOtherVersions(postId, labelId, labelName, labelColor, wrapper);
     702
     703                    // Keep frontend cache in sync to avoid stale labels after AJAX list refresh
     704                    syncPostLabelsCacheAdd(postId, labelId, labelName, labelColor);
    672705                   
    673706                    // REINITIALIZE drag and drop for new elements
     
    718751                    // SYNCHRONIZATION: Remove label from BOTH versions (inline and column) for same post
    719752                    syncRemoveLabelFromAllVersions(postId, labelId);
     753
     754                    // Keep frontend cache in sync to avoid stale labels after AJAX list refresh
     755                    syncPostLabelsCacheRemove(postId, labelId);
    720756                   
    721757                    // IMPORTANT: Invalidate ALL dropdowns (including current one)
     
    903939                            var allName = allMatch[1];
    904940                            var hasCheckmark = allBadge.hasClass('current');
    905                             var checkmarkHtml = hasCheckmark ? '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
     941                            var checkmarkHtml = hasCheckmark ? '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
    906942                            allBadge.html(allName + ' (' + total + ')' + checkmarkHtml);
    907943                        }
     
    916952                            var noLabelName = noLabelMatch[1];
    917953                            var hasNoLabelCheckmark = noLabelBadge.hasClass('current');
    918                             var noLabelCheckmarkHtml = hasNoLabelCheckmark ? '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
     954                            var noLabelCheckmarkHtml = hasNoLabelCheckmark ? '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
    919955                            noLabelBadge.html(noLabelName + ' (' + counts.no_label.count + ')' + noLabelCheckmarkHtml);
    920956                        }
     
    956992                                // ✅ Preserve checkmark if filter is active
    957993                                var hasCheckmark = filterBadge.hasClass('current');
    958                                 var checkmarkHtml = hasCheckmark ? '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
     994                                var checkmarkHtml = hasCheckmark ? '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>' : '';
    959995                                filterBadge.html(newText + checkmarkHtml);
    960996                            }
     
    18741910            '<div class="widget-editor-header">' +
    18751911                '<div class="widget-preview-large">' +
    1876                     '<span class="widget-preview-badge" style="display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; background: #2271b1; color: white; border-radius: 20px; font-size: 14px; font-weight: 500; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">' +
    1877                         '<span class="dashicons dashicons-chart-pie" style="font-size: 16px; width: 16px; height: 16px;"></span>' +
     1912                    '<span class="widget-preview-badge">' +
     1913                        '<span class="dashicons dashicons-chart-pie"></span>' +
    18781914                        '<span class="widget-preview-title">' + __('New Widget') + '</span>' +
    18791915                    '</span>' +
     
    18931929                '</div>' +
    18941930                '<div class="widget-field-row">' +
    1895                     '<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">' +
     1931                    '<div class="widget-two-col-grid">' +
    18961932                        '<div class="widget-field-group">' +
    18971933                            '<label class="widget-field-label">' + __('Content Type') + '</label>' +
     
    19121948                    '</div>' +
    19131949                '</div>' +
    1914                 '<div class="widget-bar-chart-options" data-widget-key="' + widgetKey + '" style="display: none; margin-top: 15px;">' +
    1915                     '<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">' +
     1950                '<div class="widget-bar-chart-options" data-widget-key="' + widgetKey + '" style="display: none;">' +
     1951                    '<div class="widget-two-col-grid">' +
    19161952                        '<div class="widget-field-group">' +
    19171953                            '<label class="widget-field-label">' + __('Orientation') + '</label>' +
     
    19391975                        labelsHtml +
    19401976                    '</div>' +
    1941                     '<div class="widget-selected-labels-container" style="margin-top: 15px; display: none;">' +
    1942                         '<div style="font-weight: 600; margin-bottom: 10px; color: #23282d;">' +
    1943                             '<span class="dashicons dashicons-sort" style="font-size: 16px; margin-right: 5px;"></span>' +
    1944                             __('Labels Order') + ' <span style="font-weight: normal; color: #666; font-size: 12px;">(' + __('Drag to reorder') + ')</span>' +
     1977                    '<div class="widget-selected-labels-container" style="display: none;">' +
     1978                        '<div class="widget-selected-labels-title">' +
     1979                            '<span class="dashicons dashicons-sort"></span>' +
     1980                            __('Labels Order') + ' <span class="widget-selected-labels-note">(' + __('Drag to reorder') + ')</span>' +
    19451981                        '</div>' +
    1946                         '<div class="widget-selected-labels-list" data-widget-key="' + widgetKey + '" style="display: flex; flex-wrap: wrap; gap: 8px; padding: 12px; background: #f9f9f9; border-radius: 4px; min-height: 50px;">' +
     1982                        '<div class="widget-selected-labels-list" data-widget-key="' + widgetKey + '">' +
    19471983                        '</div>' +
    19481984                    '</div>' +
    1949                     '<small class="field-description" style="margin-top: 8px; color: #666;">' +
     1985                    '<small class="field-description field-description-spaced">' +
    19501986                        __('Select which labels to include in this widget. Check "All labels" to include all available labels.') +
    19511987                    '</small>' +
     
    20972133        if ($(this).is(':checked')) {
    20982134            // Add to sortable list
    2099             var $labelItem = $('<div class="widget-sortable-label" data-label-key="' + labelKey + '" style="cursor: move; padding: 6px 12px; background: ' + labelColor + '; color: #fff; border-radius: 4px; display: flex; align-items: center; gap: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">' +
    2100                 '<span class="dashicons dashicons-menu" style="font-size: 14px;"></span>' +
     2135            var $labelItem = $('<div class="widget-sortable-label" data-label-key="' + labelKey + '" style="background: ' + labelColor + ';">' +
     2136                '<span class="dashicons dashicons-menu"></span>' +
    21012137                labelName +
    21022138                '<input type="hidden" name="widgets[' + widgetKey + '][label_order][]" value="' + labelKey + '">' +
  • redshape-easy-labels/trunk/includes/admin-page.php

    r3398988 r3465229  
    357357                                ?>
    358358                            </div>
    359                             <small class="field-description" style="margin-top: 8px; color: #666;">
     359                            <small class="field-description field-description-spaced">
    360360                                <?php redshape_easylabels_cl_e('If no type is selected, the label will be visible on all enabled content types.'); ?>
    361361                            </small>
     
    363363                       
    364364                        <!-- NUOVO: Opzioni di visualizzazione nei filtri -->
    365                         <div class="label-display-options" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid #e5e5e5;">
     365                        <div class="label-display-options">
    366366                            <!-- Checkbox Percentuale -->
    367                             <label class="label-checkbox-option" style="margin-bottom: 12px;">
     367                            <label class="label-checkbox-option label-checkbox-option-spaced">
    368368                                <input type="checkbox"
    369369                                       name="labels[<?php echo esc_attr($redshape_easylabels_key); ?>][show_percentage]"
     
    371371                                       <?php checked(!empty($redshape_easylabels_label['show_percentage'])); ?> />
    372372                                <span class="checkbox-label">
    373                                     <span class="dashicons dashicons-chart-pie" style="color: #2271b1;"></span>
     373                                    <span class="dashicons dashicons-chart-pie icon-accent"></span>
    374374                                    <strong><?php redshape_easylabels_cl_e('Show percentage in filters'); ?></strong>
    375375                                </span>
    376376                            </label>
    377                             <small class="field-description" style="margin-left: 24px; display: block; margin-bottom: 12px; color: #666;">
     377                            <small class="field-description field-description-indented field-description-with-bottom-gap">
    378378                                <?php redshape_easylabels_cl_e('Display percentage (2 decimals) relative to total posts next to count'); ?>
    379379                            </small>
     
    386386                                       <?php checked(!empty($redshape_easylabels_label['show_fraction'])); ?> />
    387387                                <span class="checkbox-label">
    388                                     <span class="dashicons dashicons-editor-justify" style="color: #2271b1;"></span>
     388                                    <span class="dashicons dashicons-editor-justify icon-accent"></span>
    389389                                    <strong><?php redshape_easylabels_cl_e('Show fraction format (e.g.: 3/5)'); ?></strong>
    390390                                </span>
    391391                            </label>
    392                             <small class="field-description" style="margin-left: 24px; display: block; margin-top: 4px; color: #666;">
     392                            <small class="field-description field-description-indented">
    393393                                <?php redshape_easylabels_cl_e('Display count as fraction relative to total posts (e.g.: 3/5 instead of just 3)'); ?>
    394394                            </small>
     
    504504                            <div class="label-field-group flex-grow">
    505505                                <label class="label-field-label"><?php redshape_easylabels_cl_e('Label name'); ?></label>
    506                                 <div style="display: flex; gap: 8px; align-items: flex-start;">
     506                                    <div class="default-label-row">
    507507                                    <input type="text"
    508508                                           name="default_labels[all][name]"
     
    510510                                           class="label-name-input all-label-input"
    511511                                           placeholder="<?php redshape_easylabels_cl_e('e.g. All, Everything, View All'); ?>"
    512                                            style="flex: 1;" />
     512                                         />
    513513                                    <button type="button"
    514514                                            class="reset-default-label-btn"
     
    519519                                            data-default-border-color="#2271b1"
    520520                                            data-default-enabled="1"
    521                                             title="<?php redshape_easylabels_cl_e('Reset to default'); ?>"
    522                                             style="padding: 8px 12px; background: #f0f0f1; border: 1px solid #c3c4c7; border-radius: 4px; cursor: pointer; display: flex; align-items: center; gap: 4px; font-size: 13px; color: #2c3338; transition: all 0.2s;">
    523                                         <span class="dashicons dashicons-image-rotate" style="font-size: 16px; width: 16px; height: 16px;"></span>
     521                                            title="<?php redshape_easylabels_cl_e('Reset to default'); ?>">
     522                                        <span class="dashicons dashicons-image-rotate"></span>
    524523                                        <?php redshape_easylabels_cl_e('Reset'); ?>
    525524                                    </button>
     
    542541                        <div class="label-field-group">
    543542                            <label class="label-field-label">
    544                                 <span class="dashicons dashicons-admin-customizer" style="color: #2271b1; font-size: 16px;"></span>
     543                                <span class="dashicons dashicons-admin-customizer icon-accent icon-sm"></span>
    545544                                <?php redshape_easylabels_cl_e('Border Style'); ?>
    546545                            </label>
    547                             <div class="border-style-options" style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;">
     546                            <div class="border-style-options border-style-options-grid">
    548547                                <?php
    549548                                $redshape_easylabels_current_all_border_style = !empty($redshape_easylabels_default_label_settings['all']['border_style']) ? $redshape_easylabels_default_label_settings['all']['border_style'] : 'none';
     
    574573                        <div class="label-field-group all-border-color-field" style="<?php echo empty($redshape_easylabels_default_label_settings['all']['border_style']) || $redshape_easylabels_default_label_settings['all']['border_style'] === 'none' ? 'display: none;' : ''; ?>">
    575574                            <label class="label-field-label">
    576                                 <span class="dashicons dashicons-art" style="color: #2271b1; font-size: 16px;"></span>
     575                                <span class="dashicons dashicons-art icon-accent icon-sm"></span>
    577576                                <?php redshape_easylabels_cl_e('Border Color'); ?>
    578577                            </label>
     
    625624                            <div class="label-field-group flex-grow">
    626625                                <label class="label-field-label"><?php redshape_easylabels_cl_e('Label name'); ?></label>
    627                                 <div style="display: flex; gap: 8px; align-items: flex-start;">
     626                                    <div class="default-label-row">
    628627                                    <input type="text"
    629628                                           name="default_labels[none][name]"
     
    631630                                           class="label-name-input none-label-input"
    632631                                           placeholder="<?php redshape_easylabels_cl_e('e.g. No Label, Unlabeled, Without Labels'); ?>"
    633                                            style="flex: 1;" />
     632                                         />
    634633                                    <button type="button"
    635634                                            class="reset-default-label-btn"
     
    640639                                            data-default-border-color="#646970"
    641640                                            data-default-enabled="1"
    642                                             title="<?php redshape_easylabels_cl_e('Reset to default'); ?>"
    643                                             style="padding: 8px 12px; background: #f0f0f1; border: 1px solid #c3c4c7; border-radius: 4px; cursor: pointer; display: flex; align-items: center; gap: 4px; font-size: 13px; color: #2c3338; transition: all 0.2s;">
    644                                         <span class="dashicons dashicons-image-rotate" style="font-size: 16px; width: 16px; height: 16px;"></span>
     641                                            title="<?php redshape_easylabels_cl_e('Reset to default'); ?>">
     642                                        <span class="dashicons dashicons-image-rotate"></span>
    645643                                        <?php redshape_easylabels_cl_e('Reset'); ?>
    646644                                    </button>
     
    663661                        <div class="label-field-group">
    664662                            <label class="label-field-label">
    665                                 <span class="dashicons dashicons-admin-customizer" style="color: #2271b1; font-size: 16px;"></span>
     663                                <span class="dashicons dashicons-admin-customizer icon-accent icon-sm"></span>
    666664                                <?php redshape_easylabels_cl_e('Border Style'); ?>
    667665                            </label>
    668                             <div class="border-style-options" style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;">
     666                            <div class="border-style-options border-style-options-grid">
    669667                                <?php
    670668                                $redshape_easylabels_current_border_style = !empty($redshape_easylabels_default_label_settings['none']['border_style']) ? $redshape_easylabels_default_label_settings['none']['border_style'] : 'none';
     
    695693                        <div class="label-field-group none-border-color-field" style="<?php echo empty($redshape_easylabels_default_label_settings['none']['border_style']) || $redshape_easylabels_default_label_settings['none']['border_style'] === 'none' ? 'display: none;' : ''; ?>">
    696694                            <label class="label-field-label">
    697                                 <span class="dashicons dashicons-art" style="color: #2271b1; font-size: 16px;"></span>
     695                                <span class="dashicons dashicons-art icon-accent icon-sm"></span>
    698696                                <?php redshape_easylabels_cl_e('Border Color'); ?>
    699697                            </label>
     
    10561054                <div class="backup-actions">
    10571055                    <div class="file-upload-wrapper">
    1058                         <input type="file" id="import-file" accept=".json" style="display: none;" />
     1056                        <input type="file" id="import-file" accept=".json" class="hidden-file-input" />
    10591057                        <button type="button" id="select-import-file" class="button button-secondary button-hero">
    10601058                            <span class="dashicons dashicons-media-default"></span>
     
    10641062                    </div>
    10651063                   
    1066                     <button type="button" id="import-settings" class="button button-primary button-hero" style="display: none;">
     1064                    <button type="button" id="import-settings" class="button button-primary button-hero is-hidden">
    10671065                        <span class="dashicons dashicons-upload"></span>
    10681066                        <span><?php redshape_easylabels_cl_e('Import Settings'); ?></span>
     
    11101108                    <div class="widget-editor-header">
    11111109                        <div class="widget-preview-large">
    1112                             <span class="widget-preview-badge" style="display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; background: #2271b1; color: white; border-radius: 20px; font-size: 14px; font-weight: 500; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
    1113                                 <span class="dashicons dashicons-chart-pie" style="font-size: 16px; width: 16px; height: 16px;"></span>
     1110                            <span class="widget-preview-badge">
     1111                                <span class="dashicons dashicons-chart-pie"></span>
    11141112                                <span class="widget-preview-title"><?php echo esc_html($redshape_easylabels_widget['title']); ?></span>
    11151113                            </span>
     
    11331131                       
    11341132                        <div class="widget-field-row">
    1135                             <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
     1133                            <div class="widget-two-col-grid">
    11361134                                <div class="widget-field-group">
    11371135                                    <label class="widget-field-label"><?php redshape_easylabels_cl_e('Content Type'); ?></label>
     
    11591157                           
    11601158                            <!-- Bar Chart Options -->
    1161                             <div class="widget-bar-chart-options" data-widget-key="<?php echo esc_attr($redshape_easylabels_widget_key); ?>" style="display: <?php echo ($redshape_easylabels_widget['visualization_type'] === 'bar_chart') ? 'block' : 'none'; ?>; margin-top: 15px;">
    1162                                 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
     1159                            <div class="widget-bar-chart-options" data-widget-key="<?php echo esc_attr($redshape_easylabels_widget_key); ?>" style="display: <?php echo ($redshape_easylabels_widget['visualization_type'] === 'bar_chart') ? 'block' : 'none'; ?>;">
     1160                                <div class="widget-two-col-grid">
    11631161                                    <div class="widget-field-group">
    11641162                                        <label class="widget-field-label"><?php redshape_easylabels_cl_e('Orientation'); ?></label>
     
    12531251                           
    12541252                            <!-- Selected Labels Sortable List -->
    1255                             <div class="widget-selected-labels-container" style="margin-top: 15px; display: <?php echo (!empty($redshape_easylabels_labels_for_sortable) && !$redshape_easylabels_all_labels_checked) ? 'block' : 'none'; ?>;">
    1256                                 <div style="font-weight: 600; margin-bottom: 10px; color: #23282d;">
    1257                                     <span class="dashicons dashicons-sort" style="font-size: 16px; margin-right: 5px;"></span>
    1258                                     <?php redshape_easylabels_cl_e('Labels Order'); ?> <span style="font-weight: normal; color: #666; font-size: 12px;">(<?php redshape_easylabels_cl_e('Drag to reorder'); ?>)</span>
    1259                                 </div>
    1260                                 <div class="widget-selected-labels-list" data-widget-key="<?php echo esc_attr($redshape_easylabels_widget_key); ?>" style="display: flex; flex-wrap: wrap; gap: 8px; padding: 12px; background: #f9f9f9; border-radius: 4px; min-height: 50px;">
     1253                            <div class="widget-selected-labels-container" style="display: <?php echo (!empty($redshape_easylabels_labels_for_sortable) && !$redshape_easylabels_all_labels_checked) ? 'block' : 'none'; ?>;">
     1254                                <div class="widget-selected-labels-title">
     1255                                    <span class="dashicons dashicons-sort"></span>
     1256                                    <?php redshape_easylabels_cl_e('Labels Order'); ?> <span class="widget-selected-labels-note">(<?php redshape_easylabels_cl_e('Drag to reorder'); ?>)</span>
     1257                                </div>
     1258                                <div class="widget-selected-labels-list" data-widget-key="<?php echo esc_attr($redshape_easylabels_widget_key); ?>">
    12611259                                    <?php foreach ($redshape_easylabels_labels_for_sortable as $redshape_easylabels_selected_key):
    12621260                                        if ($redshape_easylabels_selected_key === '__no_label__'):
     
    12651263                                            $redshape_easylabels_label_color = $redshape_easylabels_no_label_color;
    12661264                                    ?>
    1267                                     <div class="widget-sortable-label" data-label-key="__no_label__" style="cursor: move; padding: 6px 12px; background: <?php echo esc_attr($redshape_easylabels_label_color); ?>; color: #fff; border-radius: 4px; display: flex; align-items: center; gap: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
    1268                                         <span class="dashicons dashicons-menu" style="font-size: 14px;"></span>
     1265                                    <div class="widget-sortable-label" data-label-key="__no_label__" style="background: <?php echo esc_attr($redshape_easylabels_label_color); ?>;">
     1266                                        <span class="dashicons dashicons-menu"></span>
    12691267                                        <?php echo esc_html($redshape_easylabels_label_name); ?>
    12701268                                        <input type="hidden" name="widgets[<?php echo esc_attr($redshape_easylabels_widget_key); ?>][label_order][]" value="__no_label__">
     
    12741272                                            $redshape_easylabels_label = $redshape_easylabels_labels[$redshape_easylabels_selected_key];
    12751273                                    ?>
    1276                                     <div class="widget-sortable-label" data-label-key="<?php echo esc_attr($redshape_easylabels_selected_key); ?>" style="cursor: move; padding: 6px 12px; background: <?php echo esc_attr($redshape_easylabels_label['color']); ?>; color: #fff; border-radius: 4px; display: flex; align-items: center; gap: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
    1277                                         <span class="dashicons dashicons-menu" style="font-size: 14px;"></span>
     1274                                    <div class="widget-sortable-label" data-label-key="<?php echo esc_attr($redshape_easylabels_selected_key); ?>" style="background: <?php echo esc_attr($redshape_easylabels_label['color']); ?>;">
     1275                                        <span class="dashicons dashicons-menu"></span>
    12781276                                        <?php echo esc_html($redshape_easylabels_label['name']); ?>
    12791277                                        <input type="hidden" name="widgets[<?php echo esc_attr($redshape_easylabels_widget_key); ?>][label_order][]" value="<?php echo esc_attr($redshape_easylabels_selected_key); ?>">
     
    12841282                                </div>
    12851283                            </div>
    1286                             <small class="field-description" style="margin-top: 8px; color: #666;">
     1284                            <small class="field-description field-description-spaced">
    12871285                                <?php redshape_easylabels_cl_e('Select which labels to include in this widget. Check "All labels" to include all available labels.'); ?>
    12881286                            </small>
     
    13221320       
    13231321        <!-- Plugin Information -->
    1324         <div class="system-info-section" style="margin-bottom: 30px;">
    1325             <h3 style="margin-bottom: 15px; font-size: 18px;"><?php redshape_easylabels_cl_e('Plugin Information'); ?></h3>
    1326             <div style="background: white; padding: 20px; border: 1px solid #ddd; border-radius: 8px;">
    1327                 <table class="widefat" style="border: none;">
     1322        <div class="system-info-section">
     1323            <h3 class="system-info-title"><?php redshape_easylabels_cl_e('Plugin Information'); ?></h3>
     1324            <div class="system-info-card">
     1325                <table class="widefat system-info-table">
    13281326                    <tbody>
    13291327                        <tr>
    1330                             <td style="padding: 10px; font-weight: 600; width: 200px;"><?php redshape_easylabels_cl_e('Plugin Version'); ?></td>
    1331                             <td style="padding: 10px;"><?php echo esc_html(REDSHAPE_EASYLABELS_VERSION); ?></td>
     1328                            <td class="system-info-label"><?php redshape_easylabels_cl_e('Plugin Version'); ?></td>
     1329                            <td class="system-info-value"><?php echo esc_html(REDSHAPE_EASYLABELS_VERSION); ?></td>
    13321330                        </tr>
    1333                         <tr style="background: #f9f9f9;">
    1334                             <td style="padding: 10px; font-weight: 600;"><?php redshape_easylabels_cl_e('WordPress Version'); ?></td>
    1335                             <td style="padding: 10px;"><?php echo esc_html(get_bloginfo('version')); ?></td>
     1331                        <tr class="system-info-row-alt">
     1332                            <td class="system-info-label"><?php redshape_easylabels_cl_e('WordPress Version'); ?></td>
     1333                            <td class="system-info-value"><?php echo esc_html(get_bloginfo('version')); ?></td>
    13361334                        </tr>
    13371335                        <tr>
    1338                             <td style="padding: 10px; font-weight: 600;"><?php redshape_easylabels_cl_e('PHP Version'); ?></td>
    1339                             <td style="padding: 10px;"><?php echo esc_html(phpversion()); ?></td>
     1336                            <td class="system-info-label"><?php redshape_easylabels_cl_e('PHP Version'); ?></td>
     1337                            <td class="system-info-value"><?php echo esc_html(phpversion()); ?></td>
    13401338                        </tr>
    1341                         <tr style="background: #f9f9f9;">
    1342                             <td style="padding: 10px; font-weight: 600;"><?php redshape_easylabels_cl_e('Plugin Path'); ?></td>
    1343                             <td style="padding: 10px; font-family: monospace; font-size: 12px;"><?php echo esc_html(REDSHAPE_EASYLABELS_PLUGIN_PATH); ?></td>
     1339                        <tr class="system-info-row-alt">
     1340                            <td class="system-info-label"><?php redshape_easylabels_cl_e('Plugin Path'); ?></td>
     1341                            <td class="system-info-value system-info-path"><?php echo esc_html(REDSHAPE_EASYLABELS_PLUGIN_PATH); ?></td>
    13441342                        </tr>
    13451343                    </tbody>
  • redshape-easy-labels/trunk/includes/class-redshape-easylabels-cache.php

    r3397460 r3465229  
    3333     */
    3434    const CACHE_DURATION = 3600;
     35
     36    /**
     37     * Ottiene i post types abilitati dalle opzioni plugin con fallback retrocompatibile.
     38     *
     39     * @return array
     40     */
     41    private static function get_enabled_post_types() {
     42        $options = get_option('redshape_easylabels_options', array());
     43
     44        if (!empty($options['role_settings']['enabled_post_types']) && is_array($options['role_settings']['enabled_post_types'])) {
     45            return array_values($options['role_settings']['enabled_post_types']);
     46        }
     47
     48        // Backward compatibility con vecchia struttura opzioni.
     49        if (!empty($options['enabled_post_types']) && is_array($options['enabled_post_types'])) {
     50            return array_values($options['enabled_post_types']);
     51        }
     52
     53        return array('post', 'page');
     54    }
    3555   
    3656    /**
     
    6888    public static function invalidate_label($label_id) {
    6989        // Ottieni tutti i post types abilitati
    70         $options = get_option('redshape_easylabels_options', array());
    71         $enabled_post_types = isset($options['enabled_post_types']) ? $options['enabled_post_types'] : array('post');
     90        $enabled_post_types = self::get_enabled_post_types();
    7291       
    7392        $deleted_count = 0;
     
    152171        // Se nessun post type specificato, usa quelli abilitati nelle opzioni
    153172        if (empty($post_types)) {
    154             $options = get_option('redshape_easylabels_options', array());
    155             $post_types = isset($options['enabled_post_types']) ? $options['enabled_post_types'] : array('post');
     173            $post_types = self::get_enabled_post_types();
    156174        }
    157175       
  • redshape-easy-labels/trunk/includes/class-redshape-easylabels.php

    r3398988 r3465229  
    4141        add_action('wp_ajax_redshape_easylabels_save_filter_order', array($this, 'ajax_save_filter_order'));
    4242        add_action('wp_ajax_redshape_easylabels_get_filter_counts', array($this, 'ajax_get_filter_counts')); // NEW: Filter counts
    43         add_action('wp_ajax_redshape_easylabels_debug_post_types', array($this, 'ajax_debug_post_types'));
    4443        add_action('wp_ajax_redshape_easylabels_export_settings', array($this, 'ajax_export_settings')); // NEW: Export
    4544        add_action('wp_ajax_redshape_easylabels_import_settings', array($this, 'ajax_import_settings')); // NEW: Import
     
    5857   
    5958    private $columns_rendered = array(); // Flag to avoid double rendering
    60     private $columns_added = array(); // Flag to avoid double column addition per post type
    6159   
    6260    // Universal system - register hooks for ALL post types and check dynamically
     
    9492    // Reset flags when screen changes
    9593    public function reset_column_flags() {
    96         $this->columns_added = array();
    9794        $this->columns_rendered = array();
    9895    }
     
    242239            // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
    243240            $filter_value = sanitize_text_field(wp_unslash($_GET['content_label_filter']));
     241
     242            // Read relation for multi-filter mode (default: AND)
     243            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter parameter, no data modification
     244            $filter_relation = isset($_GET['content_label_relation']) ? strtolower(sanitize_text_field(wp_unslash($_GET['content_label_relation']))) : 'and';
     245            if (!in_array($filter_relation, array('and', 'or'), true)) {
     246                $filter_relation = 'and';
     247            }
    244248           
    245249            // Check if multiple filters (comma-separated)
    246             $filter_values = array_map('trim', explode(',', $filter_value));
     250            $filter_values = array_filter(array_map('trim', explode(',', $filter_value)));
    247251            $has_multiple = count($filter_values) > 1;
    248252           
     
    253257           
    254258            if ($has_multiple) {
    255                 // Multiple filters with AND relation
    256                 $sub_queries = array('relation' => 'AND');
     259                // Multiple filters with configurable relation (AND/OR)
     260                $sub_queries = array('relation' => strtoupper($filter_relation));
    257261               
    258262                foreach ($filter_values as $single_filter) {
     
    339343        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter parameter, no data modification
    340344        $current_filter = isset($_GET['content_label_filter']) ? sanitize_text_field(wp_unslash($_GET['content_label_filter'])) : '';
    341         $base_url = remove_query_arg('content_label_filter');
     345        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter parameter, no data modification
     346        $current_filter_relation = isset($_GET['content_label_relation']) ? strtolower(sanitize_text_field(wp_unslash($_GET['content_label_relation']))) : 'and';
     347        if (!in_array($current_filter_relation, array('and', 'or'), true)) {
     348            $current_filter_relation = 'and';
     349        }
     350
     351        $base_url = remove_query_arg(array('content_label_filter', 'content_label_relation'));
    342352       
    343353        // NUOVO: Conta i post SENZA etichette e il totale (prima di generare l'HTML)
     
    435445            $all_badge_html .= esc_html($all_name) . ' (' . intval($total_posts_count) . ')';
    436446            if ($all_class === 'current') {
    437                 $all_badge_html .= '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
     447                $all_badge_html .= '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
    438448            }
    439449            $all_badge_html .= '</span>';
     
    463473            $no_label_badge_html .= esc_html($no_label_name) . ' (' . intval($no_label_count) . ')';
    464474            if ($no_label_class === 'current') {
    465                 $no_label_badge_html .= '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
     475                $no_label_badge_html .= '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
    466476            }
    467477            $no_label_badge_html .= '</span>';
     
    484494            $quick_filter_html .= '</div>';
    485495           
    486             // Pulsante "Applica" per multi-select (inizialmente nascosto)
    487             $quick_filter_html .= '<button type="button" class="multi-select-apply-btn" id="multi-apply-btn">' . esc_html(redshape_easylabels_cl__('Apply')) . '</button>';
    488            
    489             // Separatore verticale dopo Apply
     496            // Selettore relazione AND/OR per multi-select
     497            $quick_filter_html .= '<div class="filter-relation-toggle" id="filter-relation-toggle" data-default-relation="' . esc_attr($current_filter_relation) . '">';
     498            $quick_filter_html .= '<button type="button" class="relation-btn relation-btn-and" data-relation="and">AND</button>';
     499            $quick_filter_html .= '<button type="button" class="relation-btn relation-btn-or" data-relation="or">OR</button>';
     500            $quick_filter_html .= '</div>';
     501
     502            // Separatore verticale dopo selettore relazione
    490503            $quick_filter_html .= '<span style="width: 1px; height: 16px; background-color: #ddd; margin: 0 4px;"></span>';
    491504        }
     
    593606            $badge_html .= esc_html($label['name']) . ' ' . $count_display;
    594607            if ($is_active) {
    595                 $badge_html .= '<span style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
     608                $badge_html .= '<span class="filter-checkmark" style="position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;">✓</span>';
    596609            }
    597610            $badge_html .= '</span>';
     
    712725                'post_type_enabled' => $post_type_enabled, // NUOVO: flag per il JavaScript
    713726                'translations' => $translations, // NUOVO: Traduzioni per JavaScript
    714                 'debug' => defined('WP_DEBUG') && WP_DEBUG, // Debug mode flag
    715727                'no_label_name' => $no_label_name, // Nome personalizzato per No Label
    716728                'no_label_color' => $no_label_color // Colore personalizzato per No Label
     
    878890                        border: 1px solid white;
    879891                    }
    880                     .multi-select-apply-btn {
     892                    .filter-relation-toggle {
    881893                        display: none;
    882                         background-color: #2271b1;
    883                         color: white;
    884                         padding: 4px 12px;
     894                        align-items: center;
     895                        gap: 4px;
     896                        padding: 2px;
     897                        background: #f0f0f1;
    885898                        border-radius: 12px;
     899                    }
     900                    .filter-relation-toggle.visible {
     901                        display: inline-flex;
     902                    }
     903                    .relation-btn {
     904                        border: 1px solid #c3c4c7;
     905                        background: #fff;
     906                        color: #50575e;
     907                        padding: 2px 10px;
     908                        border-radius: 10px;
    886909                        font-size: 11px;
    887                         font-weight: 500;
    888                         cursor: grab;
    889                         transition: all 0.2s ease;
    890                         position: relative;
    891                         border: 4px solid #135e96;
    892                     }
    893                     .multi-select-apply-btn:hover {
    894                         transform: scale(1.05);
    895                         box-shadow: 0 2px 4px rgba(0,0,0,0.2);
    896                     }
    897                     .multi-select-apply-btn.visible {
    898                         display: inline-block;
     910                        line-height: 1.5;
     911                        cursor: pointer;
     912                    }
     913                    .relation-btn.active {
     914                        background: #2271b1;
     915                        border-color: #2271b1;
     916                        color: #fff;
    899917                    }
    900918                ';
     
    926944                    var isMultiMode = false;
    927945                    var selectedFilters = [];
    928                     var applyBtn = $("#multi-apply-btn");
    929                    
    930                     applyBtn.on("click", function(e) {
     946                    var filterRelation = "and";
     947                    var currentSingleFilter = "";
     948                    var relationToggle = $("#filter-relation-toggle");
     949
     950                    function normalizeFromParams(params) {
     951                        isMultiMode = params.get("multi_mode") === "1";
     952                        selectedFilters = (params.get("content_label_filter") || "").split(",").filter(function(v) { return v !== ""; });
     953                        filterRelation = params.get("content_label_relation") === "or" ? "or" : "and";
     954                        currentSingleFilter = !isMultiMode && selectedFilters.length > 0 ? selectedFilters[0] : "";
     955                    }
     956
     957                    function getCheckmarkHtml() {
     958                        return "<span class=\"filter-checkmark\" style=\"position: absolute; top: -4px; right: -4px; background: #46b450; color: white; width: 14px; height: 14px; border-radius: 50%; font-size: 10px; line-height: 14px; text-align: center; font-weight: bold; border: 1px solid white;\">✓</span>";
     959                    }
     960
     961                    function setCurrentBadge(labelId) {
     962                        var allBadges = $(".filter-badge, .filter-badge-fixed");
     963                        allBadges.removeClass("current");
     964                        allBadges.find(".filter-checkmark").remove();
     965
     966                        var selector = labelId === ""
     967                            ? ".filter-badge-fixed[data-label-id=\"\"]"
     968                            : ".filter-badge[data-label-id=\"" + labelId + "\"], .filter-badge-fixed[data-label-id=\"" + labelId + "\"]";
     969
     970                        var activeBadge = $(selector).first();
     971                        if (activeBadge.length > 0) {
     972                            activeBadge.addClass("current");
     973                            if (activeBadge.find(".filter-checkmark").length === 0) {
     974                                activeBadge.append(getCheckmarkHtml());
     975                            }
     976                        }
     977                    }
     978
     979                    function updateRelationUI() {
     980                        relationToggle = $("#filter-relation-toggle");
     981                        relationToggle.find(".relation-btn").removeClass("active");
     982                        relationToggle.find(".relation-btn[data-relation=\"" + filterRelation + "\"]").addClass("active");
     983                    }
     984
     985                    function repositionFilterBar() {
     986                        var currentFilterBar = $(".content-labels-quick-filter-bar");
     987                        if (currentFilterBar.length > 0) {
     988                            if (currentFilterBar.parent().is("a")) {
     989                                currentFilterBar.unwrap();
     990                            }
     991                            var topNav = $(".tablenav.top");
     992                            if (topNav.length > 0) {
     993                                currentFilterBar.detach().insertAfter(topNav);
     994                            }
     995                            currentFilterBar.css({
     996                                "display": "block",
     997                                "float": "none",
     998                                "clear": "both",
     999                                "width": "100%"
     1000                            });
     1001                        }
     1002                    }
     1003
     1004                    function applyFiltersAjax(params) {
     1005                        var query = params.toString();
     1006                        var targetUrl = window.location.pathname + (query ? "?" + query : "");
     1007
     1008                        $.ajax({
     1009                            url: targetUrl,
     1010                            type: "GET",
     1011                            success: function(responseHtml) {
     1012                                var responseDoc = $("<div>").html(responseHtml);
     1013                                var newListTable = responseDoc.find("#posts-filter .wp-list-table").first();
     1014                                var newTopNav = responseDoc.find("#posts-filter .tablenav.top").first();
     1015                                var newBottomNav = responseDoc.find("#posts-filter .tablenav.bottom").first();
     1016
     1017                                if (newListTable.length === 0) {
     1018                                    window.location.href = targetUrl;
     1019                                    return;
     1020                                }
     1021
     1022                                var currentListTable = $("#posts-filter .wp-list-table").first();
     1023                                if (currentListTable.length > 0) {
     1024                                    currentListTable.replaceWith(newListTable);
     1025                                } else {
     1026                                    window.location.href = targetUrl;
     1027                                    return;
     1028                                }
     1029
     1030                                var currentTopNav = $("#posts-filter .tablenav.top").first();
     1031                                if (currentTopNav.length > 0 && newTopNav.length > 0) {
     1032                                    currentTopNav.replaceWith(newTopNav);
     1033                                }
     1034
     1035                                var currentBottomNav = $("#posts-filter .tablenav.bottom").first();
     1036                                if (currentBottomNav.length > 0 && newBottomNav.length > 0) {
     1037                                    currentBottomNav.replaceWith(newBottomNav);
     1038                                }
     1039
     1040                                window.history.replaceState({}, "", targetUrl);
     1041
     1042                                var appliedParams = new URLSearchParams(query);
     1043                                normalizeFromParams(appliedParams);
     1044
     1045                                updateRelationUI();
     1046                                syncMultiVisualState();
     1047                                attachBadgeHandlers();
     1048                                $(document).trigger("redshapeEasylabels:tableUpdated");
     1049                            },
     1050                            error: function() {
     1051                                window.location.href = targetUrl;
     1052                            }
     1053                        });
     1054                    }
     1055
     1056                    function syncMultiVisualState() {
     1057                        if (isMultiMode) {
     1058                            $("#filter-mode-checkbox").prop("checked", true);
     1059                            $(".filter-mode-slider").css("background-color", "#46b450");
     1060                            $(".filter-badge-fixed[data-label-id=\"\"]").hide();
     1061                            $("#filter-relation-toggle").addClass("visible");
     1062                            $(".filter-badge, .filter-badge-fixed").removeClass("multi-selected current");
     1063                            $(".filter-badge, .filter-badge-fixed").find(".filter-checkmark").remove();
     1064
     1065                            selectedFilters.forEach(function(filterId) {
     1066                                $(".filter-badge[data-label-id=\"" + filterId + "\"], .filter-badge-fixed[data-label-id=\"" + filterId + "\"]").addClass("multi-selected");
     1067                            });
     1068                        } else {
     1069                            $("#filter-mode-checkbox").prop("checked", false);
     1070                            $(".filter-mode-slider").css("background-color", "#ccc");
     1071                            $(".filter-badge-fixed[data-label-id=\"\"]").show();
     1072                            $("#filter-relation-toggle").removeClass("visible");
     1073                            $(".filter-badge, .filter-badge-fixed").removeClass("multi-selected");
     1074                            setCurrentBadge(currentSingleFilter);
     1075                        }
     1076                    }
     1077
     1078                    relationToggle.find(".relation-btn").on("click", function(e) {
    9311079                        e.preventDefault();
    932                         if (selectedFilters.length > 0) {
    933                             var params = new URLSearchParams(window.location.search);
    934                             params.set("content_label_filter", selectedFilters.join(","));
    935                             window.location.href = window.location.pathname + "?" + params.toString();
     1080                        filterRelation = $(this).data("relation") === "or" ? "or" : "and";
     1081                        updateRelationUI();
     1082
     1083                        if (isMultiMode && selectedFilters.length > 0) {
     1084                            var relationParams = new URLSearchParams(window.location.search);
     1085                            relationParams.set("multi_mode", "1");
     1086                            relationParams.set("content_label_filter", selectedFilters.join(","));
     1087                            relationParams.set("content_label_relation", filterRelation);
     1088                            applyFiltersAjax(relationParams);
    9361089                        }
    9371090                    });
     
    9451098                           
    9461099                            if (labelId === "") {
    947                                 window.location.href = filterUrl;
     1100                                var allParams = new URLSearchParams(window.location.search);
     1101                                allParams.delete("content_label_filter");
     1102                                allParams.delete("content_label_relation");
     1103                                allParams.delete("multi_mode");
     1104                                applyFiltersAjax(allParams);
    9481105                                return false;
    9491106                            }
    9501107                           
    9511108                            if (!isMulti) {
    952                                 window.location.href = filterUrl;
     1109                                applyFiltersAjax(new URLSearchParams((filterUrl.split("?")[1] || "")));
    9531110                                return false;
    9541111                            } else {
     
    9651122                                    $(this).addClass("multi-selected");
    9661123                                }
     1124
     1125                                var multiParams = new URLSearchParams(window.location.search);
     1126                                multiParams.set("multi_mode", "1");
     1127                                multiParams.set("content_label_relation", filterRelation);
     1128
     1129                                if (selectedFilters.length > 0) {
     1130                                    multiParams.set("content_label_filter", selectedFilters.join(","));
     1131                                } else {
     1132                                    multiParams.delete("content_label_filter");
     1133                                }
     1134
     1135                                applyFiltersAjax(multiParams);
    9671136                               
    9681137                                return false;
     
    9751144                    // Check if multi-mode is active from URL
    9761145                    var params = new URLSearchParams(window.location.search);
    977                     if (params.get("multi_mode") === "1") {
    978                         $("#filter-mode-checkbox").prop("checked", true);
    979                         isMultiMode = true;
    980                         $(".filter-mode-slider").css("background-color", "#46b450");
    981                         $(".filter-badge-fixed[data-label-id=\'\']").hide();
    982                         applyBtn.addClass("visible");
    983                        
    984                         var activeFilters = params.get("content_label_filter");
    985                         if (activeFilters) {
    986                             selectedFilters = activeFilters.split(",");
    987                             selectedFilters.forEach(function(filterId) {
    988                                 $(".filter-badge[data-label-id=\'" + filterId + "\'], .filter-badge-fixed[data-label-id=\'" + filterId + "\']").addClass("multi-selected");
    989                             });
    990                         }
    991                     }
     1146                    normalizeFromParams(params);
     1147
     1148                    if (!params.get("content_label_relation") && relationToggle.data("default-relation") === "or") {
     1149                        filterRelation = "or";
     1150                    }
     1151
     1152                    updateRelationUI();
     1153                    syncMultiVisualState();
    9921154                   
    9931155                    // Toggle multi-select mode
    9941156                    $("#filter-mode-checkbox").on("change", function() {
     1157                        var hadActiveFilters = selectedFilters.length > 0;
    9951158                        isMultiMode = $(this).is(":checked");
    9961159                        selectedFilters = [];
    997                         $(".filter-badge, .filter-badge-fixed").removeClass("multi-selected");
     1160                        currentSingleFilter = "";
    9981161                       
    999                         var params = new URLSearchParams(window.location.search);
    1000                         params.delete("content_label_filter");
     1162                        var toggleParams = new URLSearchParams(window.location.search);
     1163                        toggleParams.delete("content_label_filter");
     1164                        toggleParams.delete("content_label_relation");
    10011165                       
    10021166                        if (isMultiMode) {
    1003                             params.set("multi_mode", "1");
     1167                            toggleParams.set("multi_mode", "1");
     1168                            toggleParams.set("content_label_relation", filterRelation);
    10041169                        } else {
    1005                             params.delete("multi_mode");
     1170                            toggleParams.delete("multi_mode");
    10061171                        }
    1007                        
    1008                         var newUrl = window.location.pathname + (params.toString() ? "?" + params.toString() : "");
    1009                         window.location.href = newUrl;
     1172
     1173                        if (hadActiveFilters) {
     1174                            applyFiltersAjax(toggleParams);
     1175                        } else {
     1176                            window.history.replaceState({}, "", window.location.pathname + (toggleParams.toString() ? "?" + toggleParams.toString() : ""));
     1177                            syncMultiVisualState();
     1178                            updateRelationUI();
     1179                        }
    10101180                    });
    10111181                });
     
    15031673            setTimeout(function() { newCardEl.removeClass('new-label'); }, 300);
    15041674            labelCounter++;
    1505         } catch(error) {
    1506             if (typeof redshapeEasylabelsAjax !== 'undefined' && redshapeEasylabelsAjax.debug) {
    1507                 console.error('Error adding label:', error);
    1508             }
     1675        } catch(_error) {
    15091676        }
    15101677    });
  • redshape-easy-labels/trunk/readme.txt

    r3409971 r3465229  
    55Tested up to: 6.9
    66Requires PHP: 7.0
    7 Stable tag: 1.2.0
     7Stable tag: 1.3.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    7777= How does multi-select filtering work? =
    7878
    79 Toggle the Multi switch in the quick filters to enable multi-select mode. Click multiple label badges to select them (they'll show a green checkmark), then click Apply to filter posts that have ALL the selected labels together. The filter uses AND logic, so only posts with every selected label will be shown.
     79Toggle the Multi switch in the quick filters to enable multi-select mode. Click label badges to apply filters immediately (AJAX) without page reload, and choose AND or OR mode. AND returns posts that match all selected labels, while OR returns posts that match at least one selected label.
    8080
    8181== Screenshots ==
     
    9393
    9494== Changelog ==
     95
     96= 1.3.0 =
     97* Maintenance: Version bump to 1.3.0
     98* Compatibility: Tested up to WordPress 6.9
     99* New: Multi-select filters now support AND/OR relation modes
     100* Enhancement: Quick filters now apply instantly via AJAX (no Apply button)
     101* Fix: Removed duplicated uninstall cleanup blocks (cache/meta/transient)
     102* Fix: Aligned cache post type source with role_settings[enabled_post_types] and backward-compatible fallback
     103* Fix: Removed duplicate initializeLabelEvents() call in admin JavaScript
    95104
    96105= 1.2.0 =
     
    178187== Upgrade Notice ==
    179188
     189= 1.3.0 =
     190Maintenance release: metadata update (tested up to 6.9), AND/OR multi-select filtering support, and technical cleanup for uninstall, cache option consistency, and admin JS initialization.
     191
    180192= 1.2.0 =
    181193Major feature update: Adds dashboard widgets with 5 visualization types and interactive click-to-filter functionality. Includes drag & drop label ordering for complete customization.
  • redshape-easy-labels/trunk/redshape-easy-labels.php

    r3398988 r3465229  
    33 * Plugin Name: REDSHAPE Easy Labels
    44 * Description: Colored labels and internal notes system for posts and pages, visible only in backend for content organization. Supports 10 languages (IT, EN, FR, DE, ES, RU, ZH, JA, KO, HI).
    5  * Version: 1.2.0
     5 * Version: 1.3.0
    66 * Author: REDSHAPE
    77 * Author URI: https://redshape.it
     
    1818
    1919// Define plugin constants
    20 define('REDSHAPE_EASYLABELS_VERSION', '1.2.0');
     20define('REDSHAPE_EASYLABELS_VERSION', '1.3.0');
    2121define('REDSHAPE_EASYLABELS_PLUGIN_URL', plugin_dir_url(__FILE__));
    2222define('REDSHAPE_EASYLABELS_PLUGIN_PATH', plugin_dir_path(__FILE__));
     
    4848    function redshape_easylabels_cl_e($string) {
    4949        echo esc_html(Redshape_Easylabels_I18n::__($string));
    50     }
    51 }
    52 
    53 /**
    54  * Helper function for plugin logging
    55  * Only logs if WP_DEBUG is enabled to avoid production logging
    56  * Uses WordPress logging system to avoid direct error_log usage
    57  *
    58  * @param string $message The message to log
    59  */
    60 if (!function_exists('redshape_easylabels_log')) {
    61     function redshape_easylabels_log($message) {
    62         // Only log in debug mode to avoid production logging
    63         if (defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
    64             // Use WordPress debug system - writes to wp-content/debug.log
    65             $log_message = 'REDSHAPE Easy Labels: ' . $message;
    66            
    67             // Use WordPress logging system - only wp_debug_log to avoid filesystem issues
    68             if (function_exists('wp_debug_log')) {
    69                 wp_debug_log($log_message);
    70             }
    71             // If wp_debug_log is not available, silently skip logging to avoid warnings
    72         }
    7350    }
    7451}
  • redshape-easy-labels/trunk/uninstall.php

    r3397353 r3465229  
    5454// 6. CLEANUP TRANSIENTS (if any remain)
    5555delete_transient('redshape_easylabels_version_check');
    56 
    57 // 3. RIMUOVI CACHE (se presente)
    58 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    59 $wpdb->query(
    60     "DELETE FROM {$wpdb->options}
    61      WHERE option_name LIKE 'redshape_easylabels_counts_%'"
    62 );
    63 
    64 // 4. RIMUOVI TUTTI I META DATI DELLE ETICHETTE
    65 // Meta key: _content_labels (array di etichette per ogni post)
    66 delete_post_meta_by_key('_content_labels');
    67 
    68 // 5. RIMUOVI TUTTI I META DATI DELLE NOTE
    69 // Meta key: _content_note (nota testuale per ogni post)
    70 delete_post_meta_by_key('_content_note');
    71 
    72 // 6. CLEANUP TRANSIENTS (if any remain)
    73 delete_transient('redshape_easylabels_version_check');
    7456// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    7557$wpdb->query(
Note: See TracChangeset for help on using the changeset viewer.