This commit is contained in:
2026-03-26 23:26:44 +01:00
parent 84690849a1
commit be150fdb84
7 changed files with 141 additions and 25 deletions

View File

@@ -132,3 +132,17 @@ read_only_memory_patterns: []
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
line_ending:
# advanced configuration option allowing to configure language server-specific options.
# Maps the language key to the options.
# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available.
# No documentation on options means no options are available.
ls_specific_settings: {}
# list of regex patterns for memories to completely ignore.
# Matching memories will not appear in list_memories or activate_project output
# and cannot be accessed via read_memory or write_memory.
# To access ignored memory files, use the read_file tool on the raw file path.
# Extends the list from the global configuration, merging the two lists.
# Example: ["_archive/.*", "_episodes/.*"]
ignored_memory_patterns: []

View File

@@ -9,8 +9,8 @@
},
"api.php": {
"type": "-",
"size": 21983,
"lmtime": 1773396158405,
"size": 28579,
"lmtime": 1774049776000,
"modified": false
},
"autoload": {

View File

@@ -1304,6 +1304,7 @@ class Cron
'campaign_id' => $db_campaign_id,
'ad_group_id' => $ad_group_external_id,
'ad_group_name' => $ad_group_name_to_save,
'status' => 'paused',
'impressions_30' => 0,
'clicks_30' => 0,
'cost_30' => 0,

View File

@@ -1056,6 +1056,19 @@ class Products
$warningHtml = '<span class="product-warning-icon" data-warnings="' . $warningTitle . '" title="Produkt ma problemy"><i class="fa-solid fa-triangle-exclamation"></i></span>';
}
$history_campaign_id = (int) ( $row['history_campaign_id'] ?? 0 );
$history_ad_group_id = (int) ( $row['history_ad_group_id'] ?? 0 );
if ( $history_campaign_id <= 0 )
{
$history_campaign_id = (int) ( $row['campaign_id'] ?? 0 );
}
if ( $history_ad_group_id <= 0 )
{
$history_ad_group_id = (int) ( $row['ad_group_id'] ?? 0 );
}
$data['data'][] = [
'', // checkbox column
$row['product_id'],
@@ -1064,7 +1077,7 @@ class Products
htmlspecialchars( (string) ( $row['ad_group_name'] ?? '' ) ),
$product_url_html,
'<div class="table-product-title" product_id="' . $row['product_id'] . '">
<a href="/products/product_history/client_id=' . $client_id . '&product_id=' . $row['product_id'] . '&campaign_id=' . (int) ( $row['campaign_id'] ?? 0 ) . '&ad_group_id=' . (int) ( $row['ad_group_id'] ?? 0 ) . '" target="_blank" class="' . $custom_class . '">
<a href="/products/product_history/client_id=' . $client_id . '&product_id=' . $row['product_id'] . '&campaign_id=' . $history_campaign_id . '&ad_group_id=' . $history_ad_group_id . '" target="_blank" class="' . $custom_class . '">
' . $row['name'] . '
</a>
<span class="edit-product-title" product_id="' . $row['product_id'] . '">

View File

@@ -128,7 +128,8 @@ class Campaigns
FROM campaign_search_terms AS st
LEFT JOIN campaigns AS c ON c.id = st.campaign_id
LEFT JOIN campaign_ad_groups AS ag ON ag.id = st.ad_group_id
WHERE st.campaign_id = :campaign_id';
WHERE st.campaign_id = :campaign_id
AND ( st.ad_group_id IS NULL OR ag.status = \'active\' )';
$params = [ ':campaign_id' => (int) $campaign_id ];
@@ -157,7 +158,8 @@ class Campaigns
nk.match_type
FROM campaign_negative_keywords AS nk
LEFT JOIN campaign_ad_groups AS ag ON ag.id = nk.ad_group_id
WHERE nk.campaign_id = :campaign_id';
WHERE nk.campaign_id = :campaign_id
AND ( nk.ad_group_id IS NULL OR ag.status = \'active\' )';
$params = [ ':campaign_id' => (int) $campaign_id ];
@@ -198,7 +200,8 @@ class Campaigns
kw.roas_all_time
FROM campaign_keywords AS kw
LEFT JOIN campaign_ad_groups AS ag ON ag.id = kw.ad_group_id
WHERE kw.campaign_id = :campaign_id';
WHERE kw.campaign_id = :campaign_id
AND ( kw.ad_group_id IS NULL OR ag.status = \'active\' )';
$params = [ ':campaign_id' => (int) $campaign_id ];

View File

@@ -158,8 +158,10 @@ class Products
SUM( pa.impressions_30 ) AS impressions_30
FROM products_aggregate AS pa
INNER JOIN products AS p ON p.id = pa.product_id
INNER JOIN campaign_ad_groups AS ag ON ag.id = pa.ad_group_id
WHERE p.client_id = :client_id
AND pa.campaign_id = :campaign_id';
AND pa.campaign_id = :campaign_id
AND ag.status = \'active\'';
if ( $ad_group_id > 0 )
{
@@ -481,7 +483,7 @@ class Products
$params[':ad_group_id'] = $ad_group_id;
}
$sql .= ' AND ( ag.status IS NULL OR ag.status = \'active\' )';
$sql .= ' AND ag.status = \'active\'';
}
static public function get_products( $client_id, $search, $limit, $start, $order_name, $order_dir, $campaign_id = 0, $ad_group_id = 0, $custom_label_4 = '' )
@@ -519,23 +521,15 @@ class Products
p.offer_id,
p.min_roas,
COALESCE( NULLIF( TRIM( p.custom_label_3 ), \'\' ), \'\' ) AS custom_label_3,
pa.campaign_id AS campaign_id,
COALESCE( NULLIF( TRIM( c.campaign_name ), \'\' ), \'--- brak kampanii ---\' ) AS campaign_name,
CASE
WHEN COUNT( DISTINCT pa.campaign_id ) = 1 THEN MAX( pa.campaign_id )
ELSE 0
END AS campaign_id,
CASE
WHEN COUNT( DISTINCT pa.campaign_id ) > 1 THEN \'--- wiele kampanii ---\'
ELSE COALESCE( MAX( c.campaign_name ), \'--- brak kampanii ---\' )
END AS campaign_name,
CASE
WHEN COUNT( DISTINCT pa.ad_group_id ) > 1 THEN \'--- wiele grup reklam ---\'
WHEN MAX( pa.ad_group_id ) = 0 THEN \'PMax (bez grup reklam)\'
ELSE COALESCE( MAX( ag.ad_group_name ), \'--- brak grupy reklam ---\' )
WHEN pa.ad_group_id = 0 THEN \'PMax (bez grup reklam)\'
ELSE COALESCE( NULLIF( TRIM( ag.ad_group_name ), \'\' ), \'--- brak grupy reklam ---\' )
END AS ad_group_name,
CASE
WHEN COUNT( DISTINCT pa.ad_group_id ) = 1 THEN MAX( pa.ad_group_id )
ELSE 0
END AS ad_group_id,
pa.ad_group_id AS ad_group_id,
pa.campaign_id AS history_campaign_id,
pa.ad_group_id AS history_ad_group_id,
COALESCE( NULLIF( TRIM( p.title ), \'\' ), NULLIF( TRIM( p.name ), \'\' ), p.offer_id ) AS name,
SUM( pa.impressions_all_time ) AS impressions,
SUM( pa.impressions_30 ) AS impressions_30,
@@ -583,7 +577,7 @@ class Products
$params[':custom_label_4'] = '%' . $custom_label_4 . '%';
}
$sql .= ' GROUP BY p.id, p.offer_id, p.min_roas, p.custom_label_3, p.name, p.title';
$sql .= ' GROUP BY p.id, p.offer_id, p.min_roas, p.custom_label_3, p.name, p.title, pa.campaign_id, c.campaign_name, pa.ad_group_id, ag.ad_group_name';
$sql .= ' ORDER BY ' . $order_sql . ' ' . $order_dir . ', product_id DESC LIMIT ' . $start . ', ' . $limit;
return $mdb -> query( $sql, $params ) -> fetchAll( \PDO::FETCH_ASSOC );
@@ -647,7 +641,9 @@ class Products
SUM( pa.conversions_all_time ) AS total_conversions
FROM products_aggregate AS pa
INNER JOIN products AS p ON p.id = pa.product_id
INNER JOIN campaign_ad_groups AS ag ON ag.id = pa.ad_group_id
WHERE p.client_id = :client_id
AND ag.status = \'active\'
AND pa.clicks_all_time > 0',
[ ':client_id' => (int) $client_id ]
) -> fetch( \PDO::FETCH_ASSOC );
@@ -695,7 +691,7 @@ class Products
$params[':custom_label_4'] = '%' . $custom_label_4 . '%';
}
$sql .= ' GROUP BY p.id
$sql .= ' GROUP BY p.id, pa.campaign_id, pa.ad_group_id
) AS grouped_rows';
return $mdb -> query( $sql, $params ) -> fetchColumn();

View File

@@ -128,6 +128,63 @@
</div>
</div>
<style>
.products-page .select2-container {
width: 100% !important;
}
.products-page .select2-container--default .select2-selection--single {
height: 38px;
border: 1px solid #e2e8f0;
border-radius: 6px;
background: #fff;
}
.products-page .select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 36px;
padding-left: 12px;
padding-right: 36px;
font-size: 14px;
color: #2d3748;
}
.products-page .select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #6c757d;
}
.products-page .select2-container--default .select2-selection--single .select2-selection__arrow {
height: 36px;
right: 8px;
}
.products-page .select2-container--default.select2-container--focus .select2-selection--single {
border-color: #6690f4;
box-shadow: 0 0 0 3px rgba(102, 144, 244, 0.1);
}
.products-page .select2-dropdown {
border: 1px solid #e2e8f0;
border-radius: 6px;
}
.products-page .select2-search--dropdown .select2-search__field {
border: 1px solid #e2e8f0;
border-radius: 6px;
height: 34px;
padding: 6px 10px;
font-size: 14px;
}
.products-page .select2-results__option {
font-size: 14px;
}
.products-page .select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #6690f4;
color: #fff;
}
</style>
<?php
$openai_enabled = \services\GoogleAdsApi::get_setting( 'openai_enabled' ) !== '0';
$claude_enabled = \services\GoogleAdsApi::get_setting( 'claude_enabled' ) !== '0';
@@ -443,8 +500,36 @@ function products_render_columns_picker( table_instance )
);
}
}
function init_products_scope_select_search()
{
if ( typeof $.fn.select2 === 'undefined' )
{
return;
}
[ '#products_campaign_id', '#products_ad_group_id' ].forEach( function( selector ) {
var $select = $( selector );
if ( !$select.length || $select.data( 'products-select2-ready' ) )
{
return;
}
$select.select2({
width: '100%',
allowClear: true,
placeholder: '- wybierz -'
});
$select.data( 'products-select2-ready', true );
} );
}
$( function()
{
init_products_scope_select_search();
var products_table = new DataTable( '#products', {
stateSave: true,
ajax: {
@@ -694,6 +779,7 @@ $( function()
if ( !client_id )
{
$campaign.trigger( 'change.select2' );
return $.Deferred().resolve().promise();
}
@@ -714,6 +800,7 @@ $( function()
$campaign.val( selected_campaign_id );
}
$campaign.trigger( 'change.select2' );
update_delete_ad_group_button_state();
} );
}
@@ -739,6 +826,7 @@ $( function()
if ( !campaign_id )
{
$ad_group.trigger( 'change.select2' );
update_delete_ad_group_button_state();
return $.Deferred().resolve().promise();
}
@@ -757,6 +845,7 @@ $( function()
$ad_group.val( selected_ad_group_id );
}
$ad_group.trigger( 'change.select2' );
update_delete_ad_group_button_state();
} );
}