feat: Add Supplemental Feeds feature with UI and backend support
- Implemented the main view for Supplemental Feeds, displaying clients with Merchant Account IDs and their associated feed files. - Added styling for the feeds page and its components, including headers, empty states, and dropdown menus for syncing actions. - Created backend logic to generate supplemental feeds for clients, including file handling and data sanitization. - Integrated new routes and views for managing feeds, ensuring proper data retrieval and display. - Updated navigation to include the new Supplemental Feeds section. - Added necessary documentation for CRON job management related to feed generation.
This commit is contained in:
@@ -1246,7 +1246,7 @@ $( function()
|
||||
var product_id = $( this ).attr( 'product_id' );
|
||||
|
||||
$.confirm({
|
||||
title: 'Logi synchronizacji Merchant (produkt #' + product_id + ')',
|
||||
title: 'Logi zmian produktu',
|
||||
content: '<div class="merchant-logs-wrap" style="max-height:460px;overflow:auto">Ładowanie logów...</div>',
|
||||
useBootstrap: false,
|
||||
boxWidth: '1100px',
|
||||
@@ -1262,74 +1262,114 @@ $( function()
|
||||
var jc = this;
|
||||
var $wrap = jc.$content.find( '.merchant-logs-wrap' );
|
||||
|
||||
$.ajax({
|
||||
url: '/products/get_product_merchant_sync_logs/',
|
||||
type: 'POST',
|
||||
data: { product_id: product_id, limit: 100 },
|
||||
success: function( response )
|
||||
{
|
||||
var data;
|
||||
function load_logs()
|
||||
{
|
||||
$wrap.html( 'Ładowanie logów...' );
|
||||
|
||||
try
|
||||
$.ajax({
|
||||
url: '/products/get_product_merchant_sync_logs/',
|
||||
type: 'POST',
|
||||
data: { product_id: product_id, limit: 100 },
|
||||
success: function( response )
|
||||
{
|
||||
data = JSON.parse( response );
|
||||
}
|
||||
catch ( err )
|
||||
var data;
|
||||
|
||||
try
|
||||
{
|
||||
data = JSON.parse( response );
|
||||
}
|
||||
catch ( err )
|
||||
{
|
||||
$wrap.html( '<div class="text-danger">Nie udało się odczytać odpowiedzi serwera.</div>' );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( data.status !== 'ok' )
|
||||
{
|
||||
$wrap.html( '<div class="text-danger">' + escape_html( data.message || 'Błąd pobierania logów.' ) + '</div>' );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !data.logs || !data.logs.length )
|
||||
{
|
||||
$wrap.html( '<div class="text-muted">Brak logów dla tego produktu.</div>' );
|
||||
return;
|
||||
}
|
||||
|
||||
var rows_html = '';
|
||||
$.each( data.logs, function( _, log ) {
|
||||
var status_class = log.sync_status === 'success'
|
||||
? 'text-success'
|
||||
: ( log.sync_status === 'error' ? 'text-danger' : 'text-muted' );
|
||||
|
||||
rows_html += '<tr>' +
|
||||
'<td>' + escape_html( log.date_add || '' ) + '</td>' +
|
||||
'<td>' + escape_html( log.field_name || '' ) + '</td>' +
|
||||
'<td class="' + status_class + '"><b>' + escape_html( log.sync_status || '' ) + '</b></td>' +
|
||||
'<td>' + escape_html( log.sync_source || '' ) + '</td>' +
|
||||
'<td>' + escape_html( log.old_value || '' ) + '</td>' +
|
||||
'<td>' + escape_html( log.new_value || '' ) + '</td>' +
|
||||
'<td class="text-center"><button type="button" class="btn btn-sm btn-danger delete-merchant-log" data-log-id="' + log.id + '" title="Usuń log"><i class="fa fa-trash"></i></button></td>' +
|
||||
'</tr>';
|
||||
} );
|
||||
|
||||
$wrap.html(
|
||||
'<table class="table table-sm table-bordered table-striped" style="font-size:12px;">' +
|
||||
'<thead>' +
|
||||
'<tr>' +
|
||||
'<th style="min-width:140px;">Data</th>' +
|
||||
'<th style="min-width:120px;">Pole</th>' +
|
||||
'<th style="min-width:90px;">Status</th>' +
|
||||
'<th style="min-width:110px;">Źródło</th>' +
|
||||
'<th style="min-width:180px;">Stara wartość</th>' +
|
||||
'<th style="min-width:180px;">Nowa wartość</th>' +
|
||||
'<th style="width:60px;"></th>' +
|
||||
'</tr>' +
|
||||
'</thead>' +
|
||||
'<tbody>' + rows_html + '</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
},
|
||||
error: function()
|
||||
{
|
||||
$wrap.html( '<div class="text-danger">Nie udało się odczytać odpowiedzi serwera.</div>' );
|
||||
return;
|
||||
$wrap.html( '<div class="text-danger">Nie udało się pobrać logów.</div>' );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ( data.status !== 'ok' )
|
||||
load_logs();
|
||||
|
||||
$wrap.on( 'click', '.delete-merchant-log', function()
|
||||
{
|
||||
var $btn = $( this );
|
||||
var log_id = $btn.data( 'log-id' );
|
||||
|
||||
$btn.prop( 'disabled', true );
|
||||
|
||||
$.ajax({
|
||||
url: '/products/delete_product_merchant_sync_log/',
|
||||
type: 'POST',
|
||||
data: { log_id: log_id },
|
||||
success: function( response )
|
||||
{
|
||||
$wrap.html( '<div class="text-danger">' + escape_html( data.message || 'Błąd pobierania logów.' ) + '</div>' );
|
||||
return;
|
||||
}
|
||||
var data;
|
||||
|
||||
if ( !data.logs || !data.logs.length )
|
||||
try { data = JSON.parse( response ); } catch( e ) { return; }
|
||||
|
||||
if ( data.status === 'ok' )
|
||||
{
|
||||
load_logs();
|
||||
}
|
||||
else
|
||||
{
|
||||
$btn.prop( 'disabled', false );
|
||||
}
|
||||
},
|
||||
error: function()
|
||||
{
|
||||
$wrap.html( '<div class="text-muted">Brak logów synchronizacji dla tego produktu.</div>' );
|
||||
return;
|
||||
$btn.prop( 'disabled', false );
|
||||
}
|
||||
|
||||
var rows_html = '';
|
||||
$.each( data.logs, function( _, log ) {
|
||||
var status_class = log.sync_status === 'success'
|
||||
? 'text-success'
|
||||
: ( log.sync_status === 'error' ? 'text-danger' : 'text-muted' );
|
||||
|
||||
rows_html += '<tr>' +
|
||||
'<td>' + escape_html( log.date_add || '' ) + '</td>' +
|
||||
'<td>' + escape_html( log.field_name || '' ) + '</td>' +
|
||||
'<td class="' + status_class + '"><b>' + escape_html( log.sync_status || '' ) + '</b></td>' +
|
||||
'<td>' + escape_html( log.sync_source || '' ) + '</td>' +
|
||||
'<td>' + escape_html( log.old_value || '' ) + '</td>' +
|
||||
'<td>' + escape_html( log.new_value || '' ) + '</td>' +
|
||||
'<td>' + escape_html( log.error_message || '' ) + '</td>' +
|
||||
'</tr>';
|
||||
} );
|
||||
|
||||
$wrap.html(
|
||||
'<table class="table table-sm table-bordered table-striped" style="font-size:12px;">' +
|
||||
'<thead>' +
|
||||
'<tr>' +
|
||||
'<th style="min-width:140px;">Data</th>' +
|
||||
'<th style="min-width:120px;">Pole</th>' +
|
||||
'<th style="min-width:90px;">Status</th>' +
|
||||
'<th style="min-width:110px;">Źródło</th>' +
|
||||
'<th style="min-width:180px;">Stara wartość</th>' +
|
||||
'<th style="min-width:180px;">Nowa wartość</th>' +
|
||||
'<th style="min-width:220px;">Błąd</th>' +
|
||||
'</tr>' +
|
||||
'</thead>' +
|
||||
'<tbody>' + rows_html + '</tbody>' +
|
||||
'</table>'
|
||||
);
|
||||
},
|
||||
error: function()
|
||||
{
|
||||
$wrap.html( '<div class="text-danger">Nie udało się pobrać logów synchronizacji.</div>' );
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user