1{{ header }} 2{{ column_left }} 3<div id="content"> 4 <div class="page-header"> 5 <div class="container-fluid"> 6 <div class="pull-right"> 7 <a href="{{ text_video_tutorial_url_install }}" target="_blank" class="btn btn-info" data-toggle="tooltip" title="{{ button_video_tutorial_install }}"><i class="fa fa-video-camera"></i></a> 8 <a href="{{ cancel }}" class="btn btn-default" data-toggle="tooltip" title="{{ button_cancel }}"><i class="fa fa-reply"></i></a> 9 </div> 10 <h1>{{ heading_title }}</h1> 11 <ul class="breadcrumb"> 12 {% for breadcrumb in breadcrumbs %} 13 <li><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li> 14 {% endfor %} 15 </ul> 16 </div> 17 </div> 18 <div class="container-fluid"> 19 {% if not from_dashboard %} 20 {{ steps }} 21 {% endif %} 22 <div id="alerts"> 23 {% if success %} 24 <div class="alert alert-success alert-dismissible" role="alert"> 25 <button type="button" class="close" data-dismiss="alert" aria-label="{{ text_close }}"><span aria-hidden="true"><i class="fa fa-close"></i></span></button> 26 <i class="fa fa-check-circle" aria-hidden="true"></i> {{ success }} 27 </div> 28 {% endif %} 29 {% if error %} 30 <div class="alert alert-danger alert-dismissible" role="alert"> 31 <button type="button" class="close" data-dismiss="alert" aria-label="{{ text_close }}"><span aria-hidden="true"><i class="fa fa-close"></i></span></button> 32 <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> {{ error }} 33 </div> 34 {% endif %} 35 {% if warning %} 36 <div class="alert alert-warning alert-dismissible" role="alert"> 37 <button type="button" class="close" data-dismiss="alert" aria-label="{{ text_close }}"><i class="fa fa-close"></i></button> 38 <i class="fa fa-info-circle"></i> {{ warning }} 39 </div> 40 {% endif %} 41 </div> 42 <div class="row"> 43 <div class="col-md-9"> 44 <div class="panel panel-default"> 45 <div class="panel-heading"> 46 <h3 class="panel-title"> 47 <i class="fa fa-pencil"></i> 48 <span> 49 {% if from_dashboard %} 50 {{ text_panel_heading_campaign_2 }} 51 {% else %} 52 {{ text_panel_heading_campaign }} 53 {% endif %} 54 </span> 55 </h3> 56 </div> 57 <div class="panel-body"> 58 <form action="{{ action }}" method="post" enctype="multipart/form-data" id="form" class="form-horizontal"> 59 <div class="form-group required"> 60 <label class="col-sm-2 control-label">{{ entry_campaign }}</label> 61 <div class="col-sm-10"> 62 <div id="targets"> 63 {% if targets %} 64 <div class="table-responsive"> 65 <table class="table table-bordered table-hover"> 66 <thead> 67 <tr> 68 <th class="text-left">{{ entry_campaign_name }}</th> 69 <th class="text-center">{{ entry_country }}</th> 70 <th class="text-center">{{ entry_budget }}</th> 71 <th class="text-left">{{ entry_feed }}</th> 72 <th class="text-center">{{ entry_roas }}</th> 73 <th class="text-center">{{ entry_status }}</th> 74 <th class="text-right">{{ entry_action }}</th> 75 </tr> 76 </thead> 77 <tbody id="list"> 78 {% for target in targets %} 79 <tr> 80 <td class="text-left">{{ target.campaign_name }}</td> 81 <td class="text-center">{{ target.country.name }}</td> 82 <td class="text-center">{{ target.budget.formatted }}</td> 83 <td class="text-left"> 84 <ul> 85 {% for feed in target.feeds %} 86 <li>{{ feed.text }}</li> 87 {% endfor %} 88 </ul> 89 </td> 90 <td class="text-center"> 91 {% if target.roas_status %} 92 {{ target.roas }}% 93 {% else %} 94 <span class="label label-default" data-toggle="tooltip" data-original-title="{{ target.roas_warning }}">{{ text_label_unavailable }}</span> 95 {% endif %} 96 </td> 97 <td class="text-center"> 98 {% if target.status == 'paused' %} 99 <span class="label label-warning">{{ text_label_paused }}</span> 100 {% elseif target.status == 'active' %} 101 <span class="label label-success">{{ text_label_active }}</span> 102 {% endif %} 103 </td> 104 <td class="text-right"> 105 <button class="btn btn-primary button-target-edit" data-toggle="tooltip" title="{{ button_edit }}" data-target-id="{{ target.target_id }}"><i class="fa fa-pencil"></i></button> 106 <button class="btn btn-danger button-target-delete" data-toggle="tooltip" title="{{ button_delete }}" data-target-id="{{ target.target_id }}"><i class="fa fa-trash"></i></button> 107 </td> 108 </tr> 109 {% endfor %} 110 </tbody> 111 </table> 112 </div> 113 {% else %} 114 <div class="alert alert-warning"><i class="fa fa-warning"></i> {{ text_no_targets }}</div> 115 {% endif %} 116 </div> 117 <div> 118 <button id="button-target-add" class="btn btn-default"><i class="fa fa-plus"></i> {{ button_add_target }}</button> 119 </div> 120 </div> 121 </div> 122 <!--div class="form-group"> 123 <label class="col-sm-2 control-label">{{ entry_auto_advertise }}</label> 124 <div class="col-sm-10"> 125 <label class="radio-inline"> 126 <input type="radio" name="advertise_google_auto_advertise" value="1" {{ advertise_google_auto_advertise == '1' ? 'checked="checked"' }}> 127 {{ text_yes }} 128 </label> 129 <label class="radio-inline"> 130 <input type="radio" name="advertise_google_auto_advertise" value="0" {{ advertise_google_auto_advertise == '0' ? 'checked="checked"' }}> 131 {{ text_no }} 132 </label> 133 </div> 134 </div--> 135 <hr /> 136 {% if not from_dashboard %} 137 <div class="alert alert-info text-left"> 138 <div class="checkbox"> 139 <label><input type="checkbox" class="acknowledge" /> {{ text_acknowledge_add_campaign_1 }}</label> 140 </div> 141 <div class="checkbox"> 142 <label><input type="checkbox" class="acknowledge" /> {{ text_acknowledge_add_campaign_2 }}</label> 143 </div> 144 </div> 145 {% endif %} 146 <div class="pull-right"> 147 <button type="submit" {{ not from_dashboard ? 'disabled' }} class="btn btn-primary" id="proceed">{{ button_proceed }}</button> 148 </div> 149 </form> 150 </div> 151 </div> 152 </div> 153 <div class="col-md-3"> 154 <div class="panel panel-default"> 155 <div class="panel-heading"> 156 <h3 class="panel-title"><i class="fa fa-info-circle"></i> <span>{{ text_panel_heading_more_info }}</span></h3> 157 </div> 158 <div class="panel-body"> 159 {{ text_campaign_more_info }} 160 </div> 161 </div> 162 <div class="panel panel-default"> 163 <div class="panel-heading"> 164 <h3 class="panel-title"><i class="fa fa-image"></i> <span>{{ text_panel_heading_preview }}</span></h3> 165 </div> 166 <div class="panel-body text-center"> 167 <img id="ad-preview" src="view/image/advertise/google/ad-preview.png" /> 168 </div> 169 </div> 170 </div> 171 </div> 172</div> 173<style type="text/css"> 174 .feed { 175 position: relative; 176 } 177 178 .feed > .row { 179 padding-right: 60px; 180 } 181 182 .button-feed-delete { 183 position: absolute; 184 top: 9px; 185 right: 0; 186 } 187 188 #feeds > .feed:first-child > .row { 189 margin-top: -9px; 190 } 191 192 #ad-preview { 193 max-width: 100%; 194 } 195</style> 196<script type="text/template" id="template-targets"> 197 <div class="table-responsive"> 198 <table class="table table-bordered table-hover"> 199 <thead> 200 <tr> 201 <th class="text-left">{{ entry_campaign_name }}</th> 202 <th class="text-center">{{ entry_country }}</th> 203 <th class="text-center">{{ entry_budget }}</th> 204 <th class="text-left">{{ entry_feed }}</th> 205 <th class="text-center">{{ entry_roas }}</th> 206 <th class="text-center">{{ entry_status }}</th> 207 <th class="text-right">{{ entry_action }}</th> 208 </tr> 209 </thead> 210 <tbody id="list"> 211 212 </tbody> 213 </table> 214 </div> 215</script> 216<script type="text/template" id="template-list-element"> 217 <tr> 218 <td class="text-left">{campaign_name}</td> 219 <td class="text-center">{country}</td> 220 <td class="text-center">{budget}</td> 221 <td class="text-left">{feeds}</td> 222 <td class="text-center">{roas}</td> 223 <td class="text-center">{status}</td> 224 <td class="text-right"> 225 <button class="btn btn-primary button-target-edit" data-toggle="tooltip" title="{{ button_edit }}" data-target-id="{target_id}"><i class="fa fa-pencil"></i></button> 226 <button class="btn btn-danger button-target-delete" data-toggle="tooltip" title="{{ button_delete }}" data-target-id="{target_id}"><i class="fa fa-trash"></i></button> 227 </td> 228 </tr> 229</script> 230<script type="text/template" id="template-modal"> 231 <div id="target-modal" class="modal fade" tabindex="-1" role="dialog" data-backdrop="static"> 232 <div class="modal-dialog modal-lg" role="document"> 233 <div class="modal-content"> 234 <div class="modal-header"> 235 <button type="button" class="close" data-dismiss="modal"><i class="fa fa-close"></i></button> 236 <h4 class="modal-title">{title}</h4> 237 </div> 238 <div class="modal-body form-horizontal"> 239 <div id="target-alerts"></div> 240 <div class="form-group required" data-error-type="error_campaign_name"> 241 <label for="input-campaign-name" class="col-sm-3 control-label">{{ entry_campaign_name }}</label> 242 <div class="col-sm-9"> 243 <input type="text" class="form-control" id="input-campaign-name" name="campaign_name" value="{campaign_name}" /> 244 </div> 245 </div> 246 <div class="form-group"> 247 <label class="col-sm-3 control-label">{{ entry_status }}</label> 248 <div class="col-sm-9"> 249 <select class="form-control" name="status" id="select-status" data-value="{status}"> 250 <option value="active">{{ text_active }}</option> 251 <option value="paused">{{ text_paused }}</option> 252 </select> 253 </div> 254 </div> 255 <div class="form-group required" data-error-type="error_country"> 256 <label for="select-country" class="col-sm-3 control-label">{{ entry_country }}</label> 257 <div class="col-sm-9"> 258 <select class="form-control" name="country" id="select-country" data-value="{country}"> 259 <option value="">{{ text_select_country }}</option> 260 </select> 261 </div> 262 </div> 263 <div class="form-group" data-error-type="error_roas"> 264 <label for="input-roas" class="col-sm-3 control-label">{{ entry_roas }}</label> 265 <div class="col-sm-9"> 266 <div class="alert alert-info"><i class="fa fa-info-circle"></i> {{ help_roas }}</div> 267 <div id="warning-roas" class="alert alert-warning" style="display: none;"><i class="fa fa-exclamation-triangle"></i> {roas_warning}</div> 268 <div class="input-group"> 269 <input type="number" class="form-control" id="input-roas" name="roas" value="{roas}" min="0" /> 270 <div class="input-group-addon"><i class="fa fa-percent"></i></div> 271 </div> 272 </div> 273 </div> 274 <div class="form-group required" data-error-type="error_budget"> 275 <label for="input-budget" class="col-sm-3 control-label">{{ entry_budget }}</label> 276 <div class="col-sm-9"> 277 <div class="alert alert-info"><i class="fa fa-info-circle"></i> {{ help_budget }}</div> 278 <div id="warning-budget" class="alert alert-warning" style="display: none;"><i class="fa fa-exclamation-triangle"></i> {{ warning_budget }}</div> 279 <div class="input-group"> 280 <div class="input-group-addon"><i class="fa fa-dollar"></i></div> 281 <input type="number" class="form-control" id="input-budget" name="budget" value="{budget}" min="5" /> 282 <div class="input-group-addon">{{ text_usd_day }}</div> 283 </div> 284 </div> 285 </div> 286 <div class="form-group required" data-error-type="error_feed"> 287 <label class="col-sm-3 control-label">{{ entry_feed }}</label> 288 <div class="col-sm-9"> 289 <div class="alert alert-info"><i class="fa fa-info-circle"></i> {{ help_feed }}</div> 290 <div id="feeds">{feeds}</div> 291 <div> 292 <button id="button-feed-add" class="btn btn-success"><i class="fa fa-plus"></i> {{ button_add_feed }}</button> 293 </div> 294 </div> 295 </div> 296 </div> 297 <div class="modal-footer"> 298 <button type="button" class="btn btn-default" data-dismiss="modal"><i class="fa fa-close"></i> {{ button_close }}</button> 299 <button type="button" class="btn btn-primary" id="button-target-save" data-text="{{ button_save }}" data-loading="{{ text_loading_please_wait }}" data-url="{url}"><i class="fa fa-save"></i> {{ button_save }}</button> 300 </div> 301 </div> 302 </div> 303 </div> 304</script> 305<script type="text/template" id="template-feed"> 306 <div class="feed" data-id="{id}"> 307 <div class="row"> 308 <div class="col-md-6 form-control-static"> 309 <select class="form-control" name="feed[{id}][language]" data-value="{language}"> 310 <option value="">{{ text_select_language }}</option> 311 {languages} 312 </select> 313 </div> 314 <div class="col-md-6 form-control-static"> 315 <select class="form-control" name="feed[{id}][currency]" data-value="{currency}"> 316 <option value="">{{ text_select_currency }}</option> 317 {currencies} 318 </select> 319 </div> 320 </div> 321 <button class="button-feed-delete btn btn-default" data-toggle="tooltip" title="{{ button_delete }}"><i class="fa fa-trash"></i></button> 322 </div> 323</script> 324<script type="text/template" id="template-alert"> 325 <div class="alert alert-{type} alert-dismissible" role="alert"> 326 <button type="button" class="close" data-dismiss="alert" aria-label="{{ text_close }}"><span aria-hidden="true"><i class="fa fa-close"></i></span></button> 327 <i class="fa fa-{icon}" aria-hidden="true"></i> {message} 328 </div> 329</script> 330<script type="text/javascript"> 331(function($) { 332 var allowed_targets = {{ json_allowed_targets }}; 333 334 var targets = {{ json_targets }}; 335 336 var id = 0; 337 338 var selector = { 339 alerts: '#alerts', 340 acknowledge: '.acknowledge', 341 save: '#proceed', 342 form: '#form', 343 target: { 344 container: '#targets', 345 list: '#list', 346 modal: '#target-modal', 347 alerts: '#target-alerts', 348 add : '#button-target-add', 349 edit: '.button-target-edit', 350 delete: '.button-target-delete', 351 country : '#select-country', 352 status : '#select-status', 353 save: '#button-target-save', 354 budget: '#input-budget', 355 warning_budget: '#warning-budget', 356 roas: '#input-roas', 357 warning_roas: '#warning-roas' 358 }, 359 feed: { 360 container: '#feeds', 361 error_type: '[data-error-type]', 362 language: 'select[name*="[language]"]', 363 currency: 'select[name*="[currency]"]', 364 add : '#button-feed-add', 365 delete: '.button-feed-delete', 366 row: '.feed' 367 }, 368 template : { 369 alert: '#template-alert', 370 modal : '#template-modal', 371 feed : '#template-feed', 372 targets: '#template-targets', 373 list_element: '#template-list-element' 374 } 375 }; 376 377 var template = function(html, data) { 378 $.map(data, function(text, key) { 379 html = html.replace(new RegExp("{" + key + "}", 'g'), text); 380 }); 381 382 return html; 383 }; 384 385 var makeModalHtml = function(data) { 386 var html = $(selector.template.modal).html(); 387 388 return template(html, data); 389 }; 390 391 var makeFeedsHtml = function(data) { 392 var html = $(selector.template.feed).html(); 393 394 data.languages = ''; 395 data.currencies = ''; 396 397 // Set the feed countries 398 $(allowed_targets).each(function(index, target) { 399 if (target.country.code == $(selector.target.country).val()) { 400 $(target.languages).each(function(index, language) { 401 data.languages += '<option value="' + language.code + '" ' + (language.status ? '' : 'disabled') + '>' + language.name + '</option>'; 402 }); 403 404 $(target.currencies).each(function(index, currency) { 405 data.currencies += '<option value="' + currency.code + '" ' + (currency.status ? '' : 'disabled') + '>' + currency.name + '</option>'; 406 }); 407 } 408 }); 409 410 return template(html, data); 411 }; 412 413 var makeAlertHtml = function(data) { 414 var html = $(selector.template.alert).html(); 415 416 return template(html, data); 417 }; 418 419 var displayError = function(container, message) { 420 $(container).html(makeAlertHtml({ 421 icon: 'exclamation-triangle', 422 type: 'danger', 423 message: message 424 })); 425 }; 426 427 var makeListElementHtml = function(data) { 428 var html = $(selector.template.list_element).html(); 429 430 return template(html, data); 431 } 432 433 var makeListElementRoasHtml = function(roas_status, roas_warning, roas) { 434 if (!roas_status) { 435 return '<span class="label label-default" data-toggle="tooltip" data-original-title="' + roas_warning + '">{{ text_label_unavailable }}</span>'; 436 } else { 437 return roas.toString() + '%'; 438 } 439 } 440 441 var makeListElementStatusHtml = function(status) { 442 if (status == 'paused') { 443 return '<span class="label label-warning">{{ text_label_paused }}</span>'; 444 } else if (status == 'active') { 445 return '<span class="label label-success">{{ text_label_active }}</span>'; 446 } 447 448 return ''; 449 } 450 451 var makeListElementFeedsHtml = function(feeds) { 452 html = '<ul>'; 453 $(feeds).each(function(index, feed) { 454 html += '<li>' + feed.text + '</li>'; 455 }); 456 html += '</ul>'; 457 458 return html; 459 } 460 461 var displaySuccess = function(message) { 462 $(selector.alerts).html(makeAlertHtml({ 463 icon: 'check-circle', 464 type: 'success', 465 message: message 466 })); 467 }; 468 469 var refreshTargets = function(callback) { 470 $.ajax({ 471 url: '{{ target_list }}', 472 type: 'GET', 473 dataType: 'json', 474 beforeSend: function() { 475 $(selector.target.container).html('<div class="alert alert-info text-center">{{ text_loading }}</div>'); 476 }, 477 complete: callback, 478 error: function(jqXHR, textStatus, errorThrown) { 479 displayError(selector.alerts, '(' + textStatus + ') ' + errorThrown); 480 }, 481 success: function(data) { 482 if (data.error) { 483 displayError(selector.alerts, data.error); 484 } else { 485 if (data.targets.length) { 486 targets = data.targets; 487 488 $(selector.target.container).html($(selector.template.targets).html()); 489 490 $(data.targets).each(function(index, target) { 491 $(selector.target.list).append(makeListElementHtml({ 492 target_id: target.target_id, 493 campaign_name: target.campaign_name, 494 country: target.country.name, 495 budget: target.budget.formatted, 496 roas: makeListElementRoasHtml(target.roas_status, target.roas_warning, target.roas), 497 status: makeListElementStatusHtml(target.status), 498 feeds: makeListElementFeedsHtml(target.feeds) 499 })); 500 }); 501 } else { 502 $(selector.target.container).html('<div class="alert alert-warning"><i class="fa fa-warning"></i> {{ text_no_targets }}</div>'); 503 } 504 } 505 } 506 }); 507 }; 508 509 var initModal = function(modalData) { 510 var html = $(makeModalHtml(modalData)); 511 512 $(html).modal(); 513 514 $(html).on('shown.bs.modal', function() { 515 // Enable tooltips 516 $('[data-toggle="tooltip"]').tooltip({container: 'body', html: true}); 517 518 // Populate countries 519 $(allowed_targets).each(function(index, target) { 520 $(selector.target.country).append('<option value="' + target.country.code + '">' + target.country.name + '</option>'); 521 }); 522 523 // Select the current country 524 $(selector.target.country).val($(selector.target.country).attr('data-value')).trigger('change'); 525 526 $(selector.target.status).val($(selector.target.status).attr('data-value')).trigger('change'); 527 528 $(selector.target.budget).trigger('change'); 529 530 $(selector.target.roas).attr('disabled', !modalData.roas_status); 531 $(selector.target.roas).attr('data-original-disabled', !modalData.roas_status ? '1' : '0'); 532 533 $(selector.target.warning_roas).toggle(!modalData.roas_status); 534 }); 535 536 $(html).on('hidden.bs.modal', function() { 537 $(this).remove(); 538 }); 539 }; 540 541 var campaignCreateTestPromise = new Promise((resolve, reject) => { 542 {% if can_edit_campaigns %} 543 resolve(); 544 {% else %} 545 var doCampaignCreateTest = function() { 546 $.ajax({ 547 url: '{{ url_campaign_test }}', 548 dataType: 'json', 549 success: function(data) { 550 if (data.status) { 551 resolve(); 552 } else if (data.redirect) { 553 document.location = data.redirect; 554 } else { 555 setTimeout(doCampaignCreateTest, 10000); 556 } 557 } 558 }); 559 }; 560 561 doCampaignCreateTest(); 562 {% endif %} 563 }); 564 565 $(document).on('click', selector.target.add, function(e) { 566 e.preventDefault(); 567 e.stopPropagation(); 568 569 var modalData = { 570 title: '{{ text_add_target }}', 571 url: '{{ target_add }}', 572 campaign_name : '', 573 budget: '25.00', 574 roas: 0, 575 roas_status: false, 576 roas_warning: '{{ text_roas_warning }}', 577 country: '', 578 status: 'active', 579 feeds: makeFeedsHtml({ 580 id: id++, 581 language: '', 582 currency: '' 583 }) 584 }; 585 586 initModal(modalData); 587 }); 588 589 $(document).on('click', selector.target.edit, function(e) { 590 e.preventDefault(); 591 e.stopPropagation(); 592 593 var data = null; 594 var feeds = ''; 595 var target_id = $(this).attr('data-target-id'); 596 597 $(targets).each(function(index, target) { 598 if (target.target_id == target_id) { 599 data = target; 600 return; 601 } 602 }); 603 604 $(data.feeds).each(function(index, feed) { 605 feeds += makeFeedsHtml({ 606 id: id++, 607 language: feed.language, 608 currency: feed.currency 609 }); 610 }); 611 612 var modalData = { 613 title: '{{ text_edit_target }}'.replace(/%s/, data.campaign_name), 614 url: '{{ target_edit }}'.replace(/{target_id}/, target_id), 615 campaign_name : data.campaign_name, 616 budget: data.budget.value, 617 roas: data.roas, 618 roas_status: data.roas_status, 619 roas_warning: data.roas_warning, 620 country: data.country.code, 621 status: data.status, 622 feeds: feeds 623 }; 624 625 initModal(modalData); 626 }); 627 628 $(document).on('click', selector.target.delete, function(e) { 629 e.preventDefault(); 630 e.stopPropagation(); 631 632 if (confirm("{{ text_confirm }}")) { 633 var target_id = $(this).attr('data-target-id'); 634 635 $(selector.target.container).html('<div class="alert alert-info text-center">{{ text_loading_please_wait }}</div>'); 636 637 campaignCreateTestPromise.then(function() { 638 $.ajax({ 639 url: '{{ target_delete }}'.replace(/{target_id}/, target_id), 640 type: 'GET', 641 dataType: 'json', 642 complete: function() { 643 refreshTargets(); 644 }, 645 error: function(jqXHR, textStatus, errorThrown) { 646 displayError(selector.alerts, '(' + textStatus + ') ' + errorThrown); 647 }, 648 success: function(data) { 649 if (data.error) { 650 displayError(selector.alerts, data.error); 651 } else if (data.redirect) { 652 document.location = data.redirect; 653 } else { 654 displaySuccess(data.success); 655 } 656 } 657 }); 658 }); 659 } 660 }); 661 662 $(document).on('click', selector.feed.add, function(e) { 663 $(selector.feed.container).append( 664 $(makeFeedsHtml({ 665 id: id++, 666 language: '', 667 currency: '' 668 })) 669 ); 670 }); 671 672 $(document).on('click', selector.feed.delete, function(e) { 673 e.preventDefault(); 674 675 if (confirm("{{ text_confirm }}")) { 676 $(this).closest(selector.feed.row).remove(); 677 } 678 }); 679 680 $(document).on('click', selector.target.save, function(e) { 681 var saveButton = this; 682 683 $(selector.target.alerts).empty(); 684 $(selector.alerts).empty(); 685 686 $(selector.target.save) 687 .text($(selector.target.save).attr('data-loading')) 688 .attr('disabled', true); 689 690 $(selector.target.modal).find('input,select').attr('disabled', true); 691 $(selector.target.modal).find(selector.feed.add).attr('disabled', true); 692 $(selector.target.modal).find(selector.feed.delete).attr('disabled', true); 693 694 $('.text-danger').remove(); 695 696 $('.has-error').removeClass('has-error'); 697 698 campaignCreateTestPromise.then(function() { 699 $.ajax({ 700 url: $(saveButton).attr('data-url'), 701 type: 'POST', 702 dataType: 'json', 703 data: $(selector.target.modal).find('input,select'), 704 complete: function() { 705 $(selector.target.save) 706 .text($(selector.target.save).attr('data-text')) 707 .attr('disabled', false); 708 709 $(selector.target.modal).find('input,select').attr('disabled', false); 710 $(selector.target.modal).find('[data-original-disabled]').each(function(index, element) { 711 $(element).attr('disabled', $(element).attr('data-original-disabled') == '1'); 712 }); 713 $(selector.target.modal).find(selector.feed.add).attr('disabled', false); 714 $(selector.target.modal).find(selector.feed.delete).attr('disabled', false); 715 }, 716 error: function(jqXHR, textStatus, errorThrown) { 717 displayError(selector.target.alerts, '(' + textStatus + ') ' + errorThrown); 718 }, 719 success: function(data) { 720 if (data.error) { 721 displayError(selector.target.alerts, data.error); 722 723 $(selector.feed.error_type).each(function(index, element) { 724 if (typeof data[$(element).attr('data-error-type')] != 'undefined') { 725 $(element).find('.col-sm-9').append('<div class="text-danger">' + data[$(element).attr('data-error-type')] + '</div>'); 726 } 727 }); 728 729 // Highlight any found errors 730 $('.text-danger').each(function() { 731 var element = $(saveButton).parent().parent(); 732 733 if (element.hasClass('form-group')) { 734 element.addClass('has-error'); 735 } 736 }); 737 } else if (data.redirect) { 738 document.location = data.redirect; 739 } else if (data.success) { 740 displaySuccess(data.success); 741 742 refreshTargets(function() { 743 $(selector.target.modal).modal('hide'); 744 }); 745 } 746 } 747 }); 748 }); 749 }); 750 751 $(document).on('change', selector.target.country, function() { 752 var code = $(this).val(); 753 754 // Set the feed countries 755 $(allowed_targets).each(function(index, target) { 756 if (target.country.code == code) { 757 $(selector.feed.container).find(selector.feed.language).find('option[value!=""]').remove(); 758 759 $(target.languages).each(function(index, language) { 760 $(selector.feed.container).find(selector.feed.language).append('<option value="' + language.code + '" ' + (language.status ? '' : 'disabled') + '>' + language.name + '</option>'); 761 }); 762 763 $(selector.feed.container).find(selector.feed.language).val( 764 $(selector.feed.container).find(selector.feed.language).attr('data-value') 765 ); 766 767 $(selector.feed.container).find(selector.feed.currency).find('option[value!=""]').remove(); 768 769 $(target.currencies).each(function(index, currency) { 770 $(selector.feed.container).find(selector.feed.currency).append('<option value="' + currency.code + '" ' + (currency.status ? '' : 'disabled') + '>' + currency.name + '</option>'); 771 }); 772 773 $(selector.feed.container).find(selector.feed.currency).val( 774 $(selector.feed.container).find(selector.feed.currency).attr('data-value') 775 ); 776 } 777 }); 778 }); 779 780 $(document).on('change', selector.acknowledge, function() { 781 $(selector.save).attr('disabled', $(selector.acknowledge + ':not(:checked)').length > 0); 782 }); 783 784 $(document).on('change keyup', selector.target.budget, function() { 785 if (parseFloat($(this).val()) < 10) { 786 $(selector.target.warning_budget).show(); 787 } else { 788 $(selector.target.warning_budget).hide(); 789 } 790 }); 791 792 $(document).on('click', selector.save, function(e) { 793 e.preventDefault(); 794 e.stopPropagation(); 795 796 $(selector.save).text('{{ text_loading_please_wait }}').attr('disabled', true); 797 $(selector.acknowledge).attr('disabled', true); 798 799 campaignCreateTestPromise.then(function() { 800 $(selector.form).submit(); 801 }); 802 }); 803})(jQuery); 804</script> 805{{ footer }}