feat: Enhance campaign terms management with keyword addition and match type change functionality
- Added a toolbar for adding keywords in the campaign terms view. - Implemented match type change functionality with a confirmation dialog. - Added delete functionality for keywords with confirmation. - Updated styles for new buttons and icons in the campaign terms view. - Enhanced product view with warning icons for product alerts and corresponding modal display. - Updated product table to include a new column for warnings and adjusted column visibility settings. - Documented project overview, code style conventions, suggested commands, and task completion checklist.
This commit is contained in:
@@ -160,6 +160,11 @@
|
||||
<div class="campaigns-extra-card-title">
|
||||
<i class="fa-solid fa-key"></i> Frazy dodane do kampanii/grup reklam
|
||||
</div>
|
||||
<div class="terms-keywords-toolbar">
|
||||
<button type="button" id="terms_add_keyword_btn" class="terms-negative-bulk-btn">
|
||||
<i class="fa-solid fa-plus"></i> Dodaj fraze
|
||||
</button>
|
||||
</div>
|
||||
<div class="campaigns-extra-table-wrap">
|
||||
<table class="table table-sm campaigns-extra-table" id="terms_keywords_table">
|
||||
<thead>
|
||||
@@ -167,6 +172,7 @@
|
||||
<th>Fraza</th>
|
||||
<th>Match type</th>
|
||||
<th>Grupa reklam</th>
|
||||
<th>Akcja</th>
|
||||
<th>Klik. all</th>
|
||||
<th>Koszt all</th>
|
||||
<th>Wartosc all</th>
|
||||
@@ -180,7 +186,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td colspan="13" class="campaigns-empty-row">Brak danych.</td></tr>
|
||||
<tr><td colspan="14" class="campaigns-empty-row">Brak danych.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -1364,6 +1370,13 @@ function terms_clear_negative_selection()
|
||||
}
|
||||
|
||||
|
||||
var MATCH_TYPE_LABELS = { 'BROAD': 'Przyblizone', 'PHRASE': 'Do wyrazenia', 'EXACT': 'Scisle' };
|
||||
function render_match_type_label( data, type ) {
|
||||
if ( type !== 'display' ) return data || '';
|
||||
var val = String( data || '' ).toUpperCase();
|
||||
return MATCH_TYPE_LABELS[val] || val;
|
||||
}
|
||||
|
||||
function build_ad_groups_table( rows )
|
||||
{
|
||||
destroy_table_if_exists( '#terms_ad_groups_table' );
|
||||
@@ -1530,7 +1543,7 @@ function build_negative_terms_table( rows )
|
||||
return '<input type="checkbox" class="terms-negative-select-row" data-negative-keyword-id="' + negative_keyword_id + '" aria-label="Zaznacz fraze do usuniecia">';
|
||||
} },
|
||||
{ data: 'keyword_text', defaultContent: '', width: '520px' },
|
||||
{ data: 'match_type', defaultContent: '' },
|
||||
{ data: 'match_type', defaultContent: '', render: render_match_type_label },
|
||||
{ data: 'id', orderable: false, searchable: false, render: function( data, type ) {
|
||||
if ( type !== 'display' ) return data;
|
||||
return '<button type="button" class="terms-remove-negative-btn" data-negative-keyword-id="' + data + '" title="Usun z wykluczajacych"><i class="fa-solid fa-trash"></i></button>';
|
||||
@@ -1597,11 +1610,16 @@ function build_keywords_table( rows )
|
||||
lengthChange: false,
|
||||
pageLength: 15,
|
||||
pagingType: 'simple_numbers',
|
||||
order: [[ 3, 'desc' ]],
|
||||
order: [[ 4, 'desc' ]],
|
||||
columns: [
|
||||
{ data: 'keyword_text', defaultContent: '' },
|
||||
{ data: 'match_type', defaultContent: '' },
|
||||
{ data: 'match_type', defaultContent: '', render: render_match_type_label },
|
||||
{ data: 'ad_group_name', defaultContent: '-' },
|
||||
{ data: 'id', orderable: false, searchable: false, render: function( data, type, row ) {
|
||||
if ( type !== 'display' ) return data;
|
||||
return '<button type="button" class="terms-change-match-type-btn" data-keyword-id="' + data + '" title="Zmien dopasowanie"><i class="fa-solid fa-pen-to-square"></i></button>' +
|
||||
' <button type="button" class="terms-delete-keyword-btn" data-keyword-id="' + data + '" title="Usun fraze"><i class="fa-solid fa-trash"></i></button>';
|
||||
} },
|
||||
{ data: 'clicks_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 0 ) : Number( data || 0 ); } },
|
||||
{ data: 'cost_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
|
||||
{ data: 'conversion_value_all_time', render: function( data, type ){ return type === 'display' ? format_num( data, 2 ) : Number( data || 0 ); } },
|
||||
@@ -1619,10 +1637,11 @@ function build_keywords_table( rows )
|
||||
columnDefs: [
|
||||
{ targets: 0, className: 'text-cell phrase-nowrap', width: '220px' },
|
||||
{ targets: [1,2], className: 'text-cell', width: '140px' },
|
||||
{ targets: [3,8], className: 'num-cell', width: '70px' },
|
||||
{ targets: [4,5,9,10], className: 'num-cell', width: '85px' },
|
||||
{ targets: [6,11], className: 'num-cell', width: '80px' },
|
||||
{ targets: [7,12], className: 'num-cell', width: '130px' }
|
||||
{ targets: 3, className: 'dt-center', width: '90px' },
|
||||
{ targets: [4,9], className: 'num-cell', width: '70px' },
|
||||
{ targets: [5,6,10,11], className: 'num-cell', width: '85px' },
|
||||
{ targets: [7,12], className: 'num-cell', width: '80px' },
|
||||
{ targets: [8,13], className: 'num-cell', width: '130px' }
|
||||
],
|
||||
language: {
|
||||
emptyTable: 'Brak danych do wyswietlenia',
|
||||
@@ -2338,6 +2357,292 @@ $( function()
|
||||
terms_ad_groups_table.columns.adjust().draw( false );
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'click', '.terms-change-match-type-btn', function()
|
||||
{
|
||||
var keyword_id = parseInt( $( this ).data( 'keyword-id' ), 10 );
|
||||
var row_data = terms_keywords_table ? terms_keywords_table.row( $( this ).closest( 'tr' ) ).data() : null;
|
||||
var keyword_text = row_data ? String( row_data.keyword_text || '' ) : '';
|
||||
var current_match = row_data ? String( row_data.match_type || 'BROAD' ).toUpperCase() : 'BROAD';
|
||||
|
||||
if ( !keyword_id ) return;
|
||||
|
||||
$.confirm({
|
||||
title: 'Zmien dopasowanie frazy',
|
||||
columnClass: 'col-md-4 col-md-offset-4',
|
||||
content:
|
||||
'<div style="margin-bottom:10px;"><strong>' + $('<span>').text( keyword_text ).html() + '</strong></div>' +
|
||||
'<div class="form-group" style="margin-bottom:0;">' +
|
||||
'<label for="kw_new_match_type" style="display:block;margin-bottom:6px;">Nowy typ dopasowania</label>' +
|
||||
'<select id="kw_new_match_type" class="form-control">' +
|
||||
'<option value="BROAD"' + ( current_match === 'BROAD' ? ' selected' : '' ) + '>Dopasowanie przyblizone</option>' +
|
||||
'<option value="PHRASE"' + ( current_match === 'PHRASE' ? ' selected' : '' ) + '>Dopasowanie do wyrazenia</option>' +
|
||||
'<option value="EXACT"' + ( current_match === 'EXACT' ? ' selected' : '' ) + '>Dopasowanie scisle</option>' +
|
||||
'</select>' +
|
||||
'<small style="display:block;margin-top:6px;color:#64748B;">Obecne: ' + current_match + '. Zmiana usunie stary keyword i doda nowy w Google Ads.</small>' +
|
||||
'</div>',
|
||||
type: 'blue',
|
||||
buttons: {
|
||||
confirm: {
|
||||
text: 'Zmien',
|
||||
btnClass: 'btn-blue',
|
||||
action: function()
|
||||
{
|
||||
var new_match_type = this.$content.find( '#kw_new_match_type' ).val() || 'BROAD';
|
||||
var modal = this;
|
||||
|
||||
if ( new_match_type === current_match )
|
||||
{
|
||||
$.alert({ title: 'Info', columnClass: 'col-md-4 col-md-offset-4', content: 'Wybrany typ dopasowania jest taki sam jak obecny.', type: 'blue' });
|
||||
return;
|
||||
}
|
||||
|
||||
modal.showLoading( true );
|
||||
|
||||
$.ajax({
|
||||
url: '/campaign_terms/update_keyword_match_type/',
|
||||
type: 'POST',
|
||||
data: { keyword_id: keyword_id, new_match_type: new_match_type },
|
||||
success: function( response )
|
||||
{
|
||||
var data = JSON.parse( response );
|
||||
modal.close();
|
||||
|
||||
if ( data.success )
|
||||
{
|
||||
var debugHtml = terms_build_debug_details_html( data.debug || null );
|
||||
var successDialog = $.alert({
|
||||
title: 'Sukces',
|
||||
columnClass: 'col-md-4 col-md-offset-4',
|
||||
content: ( data.message || 'Dopasowanie zmienione.' ) + debugHtml,
|
||||
type: 'green'
|
||||
});
|
||||
setTimeout( function() { successDialog.close(); }, 8000 );
|
||||
load_phrase_tables();
|
||||
}
|
||||
else
|
||||
{
|
||||
var debugHtml = terms_build_debug_details_html( data.debug || null );
|
||||
$.alert({
|
||||
title: 'Blad',
|
||||
columnClass: 'col-md-4 col-md-offset-4',
|
||||
content: ( data.message || 'Nie udalo sie zmienic dopasowania.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
|
||||
type: 'red'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function()
|
||||
{
|
||||
modal.close();
|
||||
$.alert({ title: 'Blad', columnClass: 'col-md-4 col-md-offset-4', content: 'Blad komunikacji z serwerem.', type: 'red' });
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
cancel: { text: 'Anuluj' }
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'click', '.terms-delete-keyword-btn', function()
|
||||
{
|
||||
var keyword_id = parseInt( $( this ).data( 'keyword-id' ), 10 );
|
||||
var row_data = terms_keywords_table ? terms_keywords_table.row( $( this ).closest( 'tr' ) ).data() : null;
|
||||
var keyword_text = row_data ? String( row_data.keyword_text || '' ) : '';
|
||||
|
||||
if ( !keyword_id ) return;
|
||||
|
||||
$.confirm({
|
||||
title: 'Usun fraze',
|
||||
columnClass: 'col-md-4 col-md-offset-4',
|
||||
content: 'Czy na pewno usunac fraze <strong>' + $('<span>').text( keyword_text ).html() + '</strong>? Operacja zostanie wyslana do Google Ads API.',
|
||||
type: 'red',
|
||||
buttons: {
|
||||
confirm: {
|
||||
text: 'Usun',
|
||||
btnClass: 'btn-red',
|
||||
keys: [ 'enter' ],
|
||||
action: function()
|
||||
{
|
||||
var modal = this;
|
||||
modal.showLoading( true );
|
||||
|
||||
$.ajax({
|
||||
url: '/campaign_terms/delete_keyword/',
|
||||
type: 'POST',
|
||||
data: { keyword_id: keyword_id },
|
||||
success: function( response )
|
||||
{
|
||||
var data = JSON.parse( response );
|
||||
modal.close();
|
||||
var debugHtml = terms_build_debug_details_html( data.debug || null );
|
||||
|
||||
if ( data.success )
|
||||
{
|
||||
$.alert({
|
||||
title: 'Sukces',
|
||||
columnClass: 'col-md-4 col-md-offset-4',
|
||||
content: ( data.message || 'Fraza zostala usunieta.' ) + debugHtml,
|
||||
type: 'green'
|
||||
});
|
||||
load_phrase_tables();
|
||||
}
|
||||
else
|
||||
{
|
||||
$.alert({
|
||||
title: 'Blad',
|
||||
columnClass: 'col-md-4 col-md-offset-4',
|
||||
content: ( data.message || 'Nie udalo sie usunac frazy.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
|
||||
type: 'red'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function()
|
||||
{
|
||||
modal.close();
|
||||
$.alert({ title: 'Blad', columnClass: 'col-md-4 col-md-offset-4', content: 'Blad komunikacji z serwerem.', type: 'red' });
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
cancel: { text: 'Anuluj' }
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'click', '#terms_add_keyword_btn', function()
|
||||
{
|
||||
var campaign_id = $( '#terms_campaign_id' ).val();
|
||||
if ( !campaign_id )
|
||||
{
|
||||
$.alert({ title: 'Uwaga', columnClass: 'col-md-4 col-md-offset-4', content: 'Wybierz kampanie przed dodaniem frazy.', type: 'orange' });
|
||||
return;
|
||||
}
|
||||
|
||||
var ad_group_options = '';
|
||||
$( '#terms_ad_group_id option' ).each( function()
|
||||
{
|
||||
var val = $( this ).val();
|
||||
if ( val )
|
||||
ad_group_options += '<option value="' + val + '">' + $('<span>').text( $( this ).text() ).html() + '</option>';
|
||||
});
|
||||
|
||||
if ( !ad_group_options )
|
||||
{
|
||||
$.alert({ title: 'Uwaga', columnClass: 'col-md-4 col-md-offset-4', content: 'Brak grup reklam. Wybierz kampanie z grupami.', type: 'orange' });
|
||||
return;
|
||||
}
|
||||
|
||||
var selected_ad_group = $( '#terms_ad_group_id' ).val() || '';
|
||||
|
||||
$.confirm({
|
||||
title: 'Dodaj fraze do grupy reklam',
|
||||
columnClass: 'col-md-4 col-md-offset-4',
|
||||
content:
|
||||
'<div class="form-group" style="margin-bottom:10px;">' +
|
||||
'<label for="add_kw_text" style="display:block;margin-bottom:6px;">Fraza</label>' +
|
||||
'<input id="add_kw_text" type="text" class="form-control" placeholder="Wpisz fraze..." />' +
|
||||
'</div>' +
|
||||
'<div class="form-group" style="margin-bottom:10px;">' +
|
||||
'<label for="add_kw_match_type" style="display:block;margin-bottom:6px;">Typ dopasowania</label>' +
|
||||
'<select id="add_kw_match_type" class="form-control">' +
|
||||
'<option value="BROAD" selected>Dopasowanie przyblizone</option>' +
|
||||
'<option value="PHRASE">Dopasowanie do wyrazenia</option>' +
|
||||
'<option value="EXACT">Dopasowanie scisle</option>' +
|
||||
'</select>' +
|
||||
'</div>' +
|
||||
'<div class="form-group" style="margin-bottom:0;">' +
|
||||
'<label for="add_kw_ad_group" style="display:block;margin-bottom:6px;">Grupa reklam</label>' +
|
||||
'<select id="add_kw_ad_group" class="form-control">' + ad_group_options + '</select>' +
|
||||
'</div>',
|
||||
type: 'blue',
|
||||
onContentReady: function()
|
||||
{
|
||||
if ( selected_ad_group )
|
||||
this.$content.find( '#add_kw_ad_group' ).val( selected_ad_group );
|
||||
},
|
||||
buttons: {
|
||||
confirm: {
|
||||
text: 'Dodaj',
|
||||
btnClass: 'btn-blue',
|
||||
action: function()
|
||||
{
|
||||
var keyword_text = $.trim( this.$content.find( '#add_kw_text' ).val() || '' );
|
||||
var match_type = this.$content.find( '#add_kw_match_type' ).val() || 'BROAD';
|
||||
var ad_group_id = this.$content.find( '#add_kw_ad_group' ).val() || '';
|
||||
var modal = this;
|
||||
|
||||
if ( keyword_text === '' )
|
||||
{
|
||||
$.alert({ title: 'Uwaga', columnClass: 'col-md-4 col-md-offset-4', content: 'Wpisz fraze do dodania.', type: 'orange' });
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !ad_group_id )
|
||||
{
|
||||
$.alert({ title: 'Uwaga', columnClass: 'col-md-4 col-md-offset-4', content: 'Wybierz grupe reklam.', type: 'orange' });
|
||||
return false;
|
||||
}
|
||||
|
||||
modal.showLoading( true );
|
||||
|
||||
$.ajax({
|
||||
url: '/campaign_terms/add_keyword/',
|
||||
type: 'POST',
|
||||
data: {
|
||||
campaign_id: campaign_id,
|
||||
ad_group_id: ad_group_id,
|
||||
keyword_text: keyword_text,
|
||||
match_type: match_type
|
||||
},
|
||||
success: function( response )
|
||||
{
|
||||
var data = JSON.parse( response );
|
||||
modal.close();
|
||||
|
||||
if ( data.success )
|
||||
{
|
||||
var debugHtml = terms_build_debug_details_html( data.debug || null );
|
||||
var successDialog = $.alert({
|
||||
title: 'Sukces',
|
||||
columnClass: 'col-md-4 col-md-offset-4',
|
||||
content: ( data.message || 'Fraza zostala dodana.' )
|
||||
+ '<br><small style="display:block;margin-top:8px;color:#64748B;">Zmiana moze byc widoczna w panelu Google Ads po 1-3 minutach.</small>'
|
||||
+ debugHtml,
|
||||
type: 'green'
|
||||
});
|
||||
setTimeout( function() { successDialog.close(); }, 10000 );
|
||||
load_phrase_tables();
|
||||
}
|
||||
else
|
||||
{
|
||||
var debugHtml = terms_build_debug_details_html( data.debug || null );
|
||||
$.alert({
|
||||
title: 'Blad',
|
||||
columnClass: 'col-md-4 col-md-offset-4',
|
||||
content: ( data.message || 'Nie udalo sie dodac frazy.' ) + ( data.error ? '<br><small>' + data.error + '</small>' : '' ) + debugHtml,
|
||||
type: 'red'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function()
|
||||
{
|
||||
modal.close();
|
||||
$.alert({ title: 'Blad', columnClass: 'col-md-4 col-md-offset-4', content: 'Blad komunikacji z serwerem.', type: 'red' });
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
cancel: { text: 'Anuluj' }
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
terms_restore_ad_groups_collapsed();
|
||||
reset_all_tables();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user