feat: custom labels toggle and inline editing in product list
Adds session-based show/hide toggle for custom labels in admin product list, inline editable fields for custom_label_0..4, and label suggestions with custom entry support. Includes repository/controller updates, UI fixes, tests, and PAUL docs release updates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,20 @@
|
||||
<?php $customLabelsEnabled = !empty( $this->custom_labels_enabled ); ?>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
var $header = $( '.panel-heading .col-sm-8' );
|
||||
if ( !$header.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $header.find( '.btn-toggle-custom-labels' ).length === 0 ) {
|
||||
var buttonClass = <?= $customLabelsEnabled ? "'btn-danger'" : "'btn-success'" ?>;
|
||||
var buttonText = <?= $customLabelsEnabled ? "'Ukryj etykiety niestandardowe'" : "'Pokaż etykiety niestandardowe'" ?>;
|
||||
$header.append( ' <a href=\"#\" class=\"btn btn-sm btn-toggle-custom-labels ' + buttonClass + '\"><i class=\"fa fa-tags mr5\"></i>' + buttonText + '</a>' );
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<? if ( $this -> shoppro_enabled ):?>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
@@ -27,10 +44,19 @@
|
||||
.product-categories {
|
||||
display: block;
|
||||
}
|
||||
.custom-label-suggestions {
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.custom-labels small {
|
||||
display: block;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
var customLabelSuggestionTimers = {};
|
||||
|
||||
// --- Inline price save ---
|
||||
$( 'body' ).on( 'change', '.product-price', function() {
|
||||
@@ -54,6 +80,139 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
// --- Toggle custom labels ---
|
||||
$( 'body' ).on( 'click', '.btn-toggle-custom-labels', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
url: '/admin/shop_product/product_custom_labels_toggle/',
|
||||
beforeSend: function() { $( '#overlay' ).show(); },
|
||||
success: function( response ) {
|
||||
$( '#overlay' ).hide();
|
||||
|
||||
var data = jQuery.parseJSON( response );
|
||||
if ( data.status === 'ok' ) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
create_error( 'Nie udało się przełączyć widoku etykiet.' );
|
||||
},
|
||||
error: function() {
|
||||
$( '#overlay' ).hide();
|
||||
create_error( 'Nie udało się przełączyć widoku etykiet.' );
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// --- Custom label suggestions + save ---
|
||||
function hideCustomLabelSuggestions( $input ) {
|
||||
var $container = $input.closest( '[class*=\"custom_label_\"]' );
|
||||
$container.find( '.custom-label-suggestions' ).hide().empty();
|
||||
var datalistId = $input.attr( 'data-datalist-id' ) || '';
|
||||
if ( datalistId ) {
|
||||
$( '#' + datalistId ).empty();
|
||||
}
|
||||
}
|
||||
|
||||
function saveCustomLabelValue( $input ) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
url: '/admin/shop_product/product_custom_label_save/',
|
||||
data: {
|
||||
product_id: $input.attr( 'data-product-id' ),
|
||||
label_type: $input.attr( 'data-label-type' ),
|
||||
custom_label: $input.val()
|
||||
},
|
||||
success: function( response ) {
|
||||
var data = jQuery.parseJSON( response );
|
||||
if ( data.status !== 'ok' ) {
|
||||
create_error( data.msg || 'Nie udało się zapisać etykiety.' );
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
create_error( 'Nie udało się zapisać etykiety.' );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadCustomLabelSuggestions( $input ) {
|
||||
var labelType = $input.attr( 'data-label-type' );
|
||||
var query = $input.val();
|
||||
var $suggestions = $input.closest( '[class*=\"custom_label_\"]' ).find( '.custom-label-suggestions' );
|
||||
var datalistId = $input.attr( 'data-datalist-id' ) || '';
|
||||
var $datalist = datalistId ? $( '#' + datalistId ) : $();
|
||||
|
||||
if ( !labelType ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
url: '/admin/shop_product/product_custom_label_suggestions/',
|
||||
data: {
|
||||
label_type: labelType,
|
||||
custom_label: query
|
||||
},
|
||||
success: function( response ) {
|
||||
var data = jQuery.parseJSON( response );
|
||||
if ( data.status !== 'ok' || !data.suggestions || !data.suggestions.length ) {
|
||||
$suggestions.hide().empty();
|
||||
$datalist.empty();
|
||||
return;
|
||||
}
|
||||
|
||||
var html = '';
|
||||
$.each( data.suggestions, function( index, item ) {
|
||||
if ( !item.label ) {
|
||||
return;
|
||||
}
|
||||
var safe = String( item.label ).replace(/\"/g, '"');
|
||||
html += '<option value=\"' + safe + '\">' + item.label + '</option>';
|
||||
});
|
||||
|
||||
if ( html ) {
|
||||
$datalist.html( html );
|
||||
$suggestions.hide().empty();
|
||||
} else {
|
||||
$suggestions.hide().empty();
|
||||
$datalist.empty();
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$suggestions.hide().empty();
|
||||
$datalist.empty();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$( 'body' ).on( 'input', '.product-custom-label', function() {
|
||||
var $input = $( this );
|
||||
var inputKey = $input.attr( 'data-product-id' ) + ':' + $input.attr( 'data-label-type' );
|
||||
|
||||
if ( customLabelSuggestionTimers[inputKey] ) {
|
||||
clearTimeout( customLabelSuggestionTimers[inputKey] );
|
||||
}
|
||||
|
||||
customLabelSuggestionTimers[inputKey] = setTimeout( function() {
|
||||
loadCustomLabelSuggestions( $input );
|
||||
}, 250 );
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'change', '.product-custom-label', function() {
|
||||
saveCustomLabelValue( $( this ) );
|
||||
});
|
||||
|
||||
$( document ).on( 'click', function(e) {
|
||||
if ( $( e.target ).closest( '.custom-labels' ).length === 0 ) {
|
||||
$( '.custom-label-suggestions' ).hide().empty();
|
||||
}
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'change', '.product-price-promo', function() {
|
||||
var $el = $( this );
|
||||
var price = $el.val().replace( ' ', '' );
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
'list' => $this->viewModel,
|
||||
'apilo_enabled' => $this->apilo_enabled,
|
||||
'shoppro_enabled' => $this->shoppro_enabled,
|
||||
'custom_labels_enabled' => $this->custom_labels_enabled,
|
||||
]); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
Reference in New Issue
Block a user