- Implemented Gemini API service for generating optimized product titles and descriptions based on Google Merchant Center guidelines. - Added settings for Gemini API key and model selection in user settings. - Enhanced product management views to support AI-generated suggestions for titles and descriptions. - Enabled state saving for various data tables across campaign, terms, logs, and products views. - Introduced AI prompt templates for generating product descriptions and categories.
193 lines
5.6 KiB
PHP
193 lines
5.6 KiB
PHP
<div class="logs-page">
|
|
<div class="logs-header">
|
|
<h2>Logi systemowe</h2>
|
|
</div>
|
|
|
|
<div class="logs-filters">
|
|
<div class="filter-group">
|
|
<label>Poziom</label>
|
|
<select id="filter_level" class="form-control">
|
|
<option value="all">Wszystkie</option>
|
|
<option value="error">Error</option>
|
|
<option value="warning">Warning</option>
|
|
<option value="info">Info</option>
|
|
</select>
|
|
</div>
|
|
<div class="filter-group">
|
|
<label>Zrodlo</label>
|
|
<select id="filter_source" class="form-control">
|
|
<option value="all">Wszystkie</option>
|
|
<?php foreach ( $this -> sources as $source ): ?>
|
|
<option value="<?= htmlspecialchars( $source, ENT_QUOTES, 'UTF-8' ); ?>"><?= htmlspecialchars( $source, ENT_QUOTES, 'UTF-8' ); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="filter-group">
|
|
<label>Data od</label>
|
|
<input type="date" id="filter_date_from" class="form-control">
|
|
</div>
|
|
<div class="filter-group">
|
|
<label>Data do</label>
|
|
<input type="date" id="filter_date_to" class="form-control">
|
|
</div>
|
|
<div class="filter-group filter-group-buttons">
|
|
<button type="button" id="filter_apply" class="btn btn-primary btn-sm">
|
|
<i class="fa-solid fa-filter"></i> Filtruj
|
|
</button>
|
|
<button type="button" id="filter_reset" class="btn btn-secondary btn-sm">
|
|
<i class="fa-solid fa-times"></i> Resetuj
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="logs-table-wrap">
|
|
<table class="table" id="logs-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Data</th>
|
|
<th>Poziom</th>
|
|
<th>Zrodlo</th>
|
|
<th>Klient</th>
|
|
<th>Wiadomosc</th>
|
|
<th style="width: 50px; text-align: center;">Akcje</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
var logsTable = null;
|
|
|
|
function getFilterParams()
|
|
{
|
|
return {
|
|
level: $( '#filter_level' ).val(),
|
|
source: $( '#filter_source' ).val(),
|
|
date_from: $( '#filter_date_from' ).val(),
|
|
date_to: $( '#filter_date_to' ).val()
|
|
};
|
|
}
|
|
|
|
function initLogsTable()
|
|
{
|
|
if ( logsTable )
|
|
{
|
|
logsTable.destroy();
|
|
$( '#logs-table tbody' ).empty();
|
|
}
|
|
|
|
logsTable = new DataTable( '#logs-table', {
|
|
stateSave: true,
|
|
ajax: {
|
|
url: '/logs/get_data_table/',
|
|
data: function( d )
|
|
{
|
|
var f = getFilterParams();
|
|
d.level = f.level;
|
|
d.source = f.source;
|
|
d.date_from = f.date_from;
|
|
d.date_to = f.date_to;
|
|
}
|
|
},
|
|
processing: true,
|
|
serverSide: true,
|
|
searching: false,
|
|
lengthChange: false,
|
|
pageLength: 25,
|
|
order: [[ 0, 'desc' ]],
|
|
columns: [
|
|
{ width: '150px', orderable: false, className: 'nowrap' },
|
|
{ width: '70px', orderable: false, className: 'dt-center' },
|
|
{ width: '140px', orderable: false },
|
|
{ width: '140px', orderable: false },
|
|
{ orderable: false },
|
|
{ width: '50px', orderable: false, className: 'dt-center' }
|
|
],
|
|
language: {
|
|
processing: 'Ladowanie...',
|
|
emptyTable: 'Brak logow do wyswietlenia',
|
|
info: 'Wpisy _START_ - _END_ z _TOTAL_',
|
|
infoEmpty: '',
|
|
paginate: { previous: '«', next: '»' }
|
|
}
|
|
});
|
|
}
|
|
|
|
$( function()
|
|
{
|
|
initLogsTable();
|
|
|
|
$( '#filter_apply' ).on( 'click', function()
|
|
{
|
|
if ( logsTable )
|
|
{
|
|
logsTable.ajax.reload( null, true );
|
|
}
|
|
});
|
|
|
|
$( '#filter_reset' ).on( 'click', function()
|
|
{
|
|
$( '#filter_level' ).val( 'all' );
|
|
$( '#filter_source' ).val( 'all' );
|
|
$( '#filter_date_from' ).val( '' );
|
|
$( '#filter_date_to' ).val( '' );
|
|
|
|
if ( logsTable )
|
|
{
|
|
logsTable.ajax.reload( null, true );
|
|
}
|
|
});
|
|
|
|
$( 'body' ).on( 'click', '.log-detail-btn', function()
|
|
{
|
|
var id = $( this ).data( 'id' );
|
|
|
|
$.ajax({
|
|
url: '/logs/get_detail/',
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
data: { id: id },
|
|
success: function( data )
|
|
{
|
|
if ( !data || !data.success )
|
|
{
|
|
$.alert({ title: 'Blad', content: ( data && data.message ) || 'Nie udalo sie pobrac szczegolow.', type: 'red' });
|
|
return;
|
|
}
|
|
|
|
var log = data.log;
|
|
var levelClass = log.level === 'error' ? 'danger' : ( log.level === 'warning' ? 'warning' : 'success' );
|
|
|
|
var html = '<div style="margin-bottom: 10px;">';
|
|
html += '<strong>Data:</strong> ' + $( '<span>' ).text( log.date_add ).html() + '<br>';
|
|
html += '<strong>Poziom:</strong> <span class="badge badge-' + levelClass + '">' + log.level + '</span><br>';
|
|
html += '<strong>Zrodlo:</strong> ' + $( '<span>' ).text( log.source || '-' ).html() + '<br>';
|
|
html += '<strong>Klient:</strong> ' + $( '<span>' ).text( log.client_name || ( log.client_id ? 'ID: ' + log.client_id : '-' ) ).html() + '<br>';
|
|
html += '<strong>Wiadomosc:</strong> ' + $( '<span>' ).text( log.message ).html();
|
|
html += '</div>';
|
|
|
|
if ( log.context )
|
|
{
|
|
html += '<div style="margin-top: 10px;">';
|
|
html += '<strong>Kontekst (JSON):</strong>';
|
|
html += '<pre style="background: #1e1e2e; color: #cdd6f4; padding: 12px; border-radius: 6px; max-height: 400px; overflow: auto; font-size: 12px; margin-top: 5px;">' + $( '<div>' ).text( log.context ).html() + '</pre>';
|
|
html += '</div>';
|
|
}
|
|
|
|
$.dialog({
|
|
title: 'Szczegoly logu #' + log.id,
|
|
content: html,
|
|
columnClass: 'xlarge'
|
|
});
|
|
},
|
|
error: function( xhr )
|
|
{
|
|
$.alert({ title: 'Blad', content: 'Blad pobierania szczegolow (HTTP ' + xhr.status + ')', type: 'red' });
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|