feat: Enhance Google Ads API integration and add column visibility control in product view

- Updated GoogleAdsApi class to include new GAQL queries for Performance Max campaigns and fallback mechanisms.
- Refactored data collection logic to handle ad groups and asset groups more effectively.
- Modified get_campaigns_30_days and get_campaigns_all_time methods to accept an optional date parameter for improved date filtering.
- Introduced a new UI feature in the products main view to allow users to toggle column visibility, enhancing user experience.
- Implemented local storage functionality to remember user preferences for column visibility across sessions.
This commit is contained in:
2026-02-18 01:50:08 +01:00
parent 4635cefcbb
commit 3dc06d505a
3 changed files with 721 additions and 137 deletions

View File

@@ -30,6 +30,13 @@
<label for="bestseller_min_roas"><i class="fa-solid fa-star"></i> Bestseller min ROAS</label>
<input type="text" id="bestseller_min_roas" name="bestseller_min_roas" class="form-control" placeholder="np. 500" value="" />
</div>
<div class="filter-group filter-group-columns">
<label><i class="fa-solid fa-table-columns"></i> Kolumny</label>
<details class="products-columns-control">
<summary>Widocznosc kolumn</summary>
<div class="products-columns-list" id="products_columns_list"></div>
</details>
</div>
</div>
<!-- Akcje bulk -->
@@ -76,9 +83,63 @@
$openai_enabled = \services\GoogleAdsApi::get_setting( 'openai_enabled' ) !== '0';
$claude_enabled = \services\GoogleAdsApi::get_setting( 'claude_enabled' ) !== '0';
?>
<style>
.products-page .products-filters .filter-group.filter-group-columns {
min-width: 240px;
}
.products-columns-control {
border: 1px solid #E2E8F0;
border-radius: 6px;
background: #FFFFFF;
overflow: hidden;
}
.products-columns-control summary {
cursor: pointer;
padding: 8px 10px;
font-size: 12px;
font-weight: 600;
color: #334155;
list-style: none;
}
.products-columns-control summary::-webkit-details-marker {
display: none;
}
.products-columns-control summary::after {
content: '\25BC';
float: right;
font-size: 10px;
color: #64748B;
margin-top: 2px;
}
.products-columns-control[open] summary::after {
content: '\25B2';
}
.products-columns-list {
border-top: 1px solid #EEF2F7;
padding: 8px 10px;
max-height: 220px;
overflow-y: auto;
}
.products-columns-list .products-col-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: #334155;
margin-bottom: 6px;
}
.products-columns-list .products-col-item:last-child {
margin-bottom: 0;
}
.products-columns-list .products-col-item input[type=checkbox] {
margin: 0;
}
</style>
<script type="text/javascript">
var AI_OPENAI_ENABLED = <?= $openai_enabled ? 'true' : 'false'; ?>;
var AI_CLAUDE_ENABLED = <?= $claude_enabled ? 'true' : 'false'; ?>;
var PRODUCTS_COLUMNS_STORAGE_KEY = 'products.columns.visibility';
var PRODUCTS_LOCKED_COLUMNS = [ 0, 19 ];
function show_toast( message, type )
{
@@ -123,6 +184,151 @@ function loadGoogleCategories( callback )
});
}
function products_storage_set( key, value )
{
try
{
if ( value === null || typeof value === 'undefined' )
{
localStorage.removeItem( key );
}
else
{
localStorage.setItem( key, String( value ) );
}
}
catch ( e ) {}
}
function products_storage_get( key )
{
try
{
return localStorage.getItem( key ) || '';
}
catch ( e )
{
return '';
}
}
function products_is_locked_column( idx )
{
return PRODUCTS_LOCKED_COLUMNS.indexOf( Number( idx ) ) !== -1;
}
function products_get_saved_columns_visibility( columns_count )
{
var raw = products_storage_get( PRODUCTS_COLUMNS_STORAGE_KEY );
if ( !raw )
{
return null;
}
try
{
var saved = JSON.parse( raw );
if ( !Array.isArray( saved ) || saved.length !== columns_count )
{
return null;
}
return saved;
}
catch ( e )
{
return null;
}
}
function products_save_columns_visibility( table_instance )
{
if ( !table_instance || !table_instance.columns )
{
return;
}
var columns_count = table_instance.columns().count();
var visible_map = [];
var i;
for ( i = 0; i < columns_count; i++ )
{
visible_map.push( table_instance.column( i ).visible() );
}
products_storage_set( PRODUCTS_COLUMNS_STORAGE_KEY, JSON.stringify( visible_map ) );
}
function products_apply_saved_columns_visibility( table_instance )
{
if ( !table_instance || !table_instance.columns )
{
return;
}
var columns_count = table_instance.columns().count();
var saved_visibility = products_get_saved_columns_visibility( columns_count );
var i;
if ( !saved_visibility )
{
return;
}
for ( i = 0; i < columns_count; i++ )
{
if ( products_is_locked_column( i ) )
{
table_instance.column( i ).visible( true, false );
continue;
}
table_instance.column( i ).visible( !!saved_visibility[i], false );
}
table_instance.columns.adjust().draw( false );
}
function products_render_columns_picker( table_instance )
{
var $list = $( '#products_columns_list' );
var columns_count = ( table_instance && table_instance.columns ) ? table_instance.columns().count() : 0;
var i;
if ( !$list.length )
{
return;
}
$list.empty();
if ( !columns_count )
{
$list.append( '<div class="products-col-item">Brak kolumn.</div>' );
return;
}
for ( i = 0; i < columns_count; i++ )
{
if ( products_is_locked_column( i ) )
{
continue;
}
var id = 'products-col-toggle-' + i;
var th = $( '#products thead th' ).eq( i );
var title = $.trim( th.find( '.dt-column-title' ).first().text() || th.text() ) || ( 'Kolumna ' + i );
var checked = table_instance.column( i ).visible() ? ' checked' : '';
$list.append(
'<label class="products-col-item" for="' + id + '">' +
'<input type="checkbox" class="products-col-toggle" id="' + id + '" data-col-index="' + i + '"' + checked + '>' +
'<span>' + title + '</span>' +
'</label>'
);
}
}
$( function()
{
var products_table = new DataTable( '#products', {
@@ -181,6 +387,9 @@ $( function()
}
});
products_apply_saved_columns_visibility( products_table );
products_render_columns_picker( products_table );
function reload_products_table()
{
products_table.ajax.reload( null, false );
@@ -648,6 +857,22 @@ $( function()
updateSelectedCount();
});
$( 'body' ).on( 'change', '.products-col-toggle', function()
{
var col_index = Number( $( this ).data( 'col-index' ) );
var is_visible = $( this ).is( ':checked' );
if ( !products_table || Number.isNaN( col_index ) || products_is_locked_column( col_index ) )
{
return;
}
products_table.column( col_index ).visible( is_visible, false );
products_table.columns.adjust().draw( false );
products_save_columns_visibility( products_table );
products_render_columns_picker( products_table );
});
// Usuwanie zaznaczonych produktów
$( 'body' ).on( 'click', '#delete-selected-products', function()
{