RenderableCampaign is a real templated thing.

This commit is contained in:
Brian Simpson
2013-08-23 11:11:04 -04:00
parent 20c14d477e
commit 4ba7d3f7dc
8 changed files with 323 additions and 401 deletions

View File

@@ -46,6 +46,7 @@ from r2.lib.pages import (
PromoteReport,
Reddit,
RefundPage,
RenderableCampaign,
Roadblocks,
UploadedImage,
)
@@ -655,17 +656,10 @@ class PromoteController(ListingController):
if campaign:
promote.edit_campaign(link, campaign, dates, bid, cpm, sr, priority)
r = promote.get_renderable_campaigns(link, campaign)
jquery.update_campaign(r.campaign_id36, r.start_date, r.end_date,
r.duration, r.bid, r.spent, r.cpm, r.sr,
r.priority_name, r.inventory_override,
r.status)
else:
campaign = promote.new_campaign(link, dates, bid, cpm, sr, priority)
r = promote.get_renderable_campaigns(link, campaign)
jquery.new_campaign(r.campaign_id36, r.start_date, r.end_date,
r.duration, r.bid, r.spent, r.cpm, r.sr,
r.priority_name, r.inventory_override, r.status)
rc = RenderableCampaign.from_campaigns(link, campaign)
jquery.update_campaign(campaign._fullname, rc.render_html())
@validatedForm(VSponsor('link_id'),
VModhash(),

View File

@@ -85,7 +85,7 @@ from r2.lib.log import log_text
from r2.lib.memoize import memoize
from r2.lib.utils import trunc_string as _truncate, to_date
from r2.lib.filters import safemarkdown
from r2.lib.utils import Storage
from r2.lib.utils import Storage, tup
from r2.lib.utils import precise_format_timedelta
from babel.numbers import format_currency
@@ -3566,7 +3566,7 @@ class PromoteLinkForm(Templated):
self.link = link
self.listing = listing
campaigns = PromoCampaign._by_link(link._id)
self.campaigns = promote.get_renderable_campaigns(link, campaigns)
self.campaigns = RenderableCampaign.from_campaigns(link, campaigns)
self.promotion_log = PromotionLog.get(link)
self.min_bid = 0 if c.user_is_sponsor else g.min_promote_bid
@@ -3594,6 +3594,51 @@ class PromoteLinkForm(Templated):
self.infobar = InfoBar(message=message)
class RenderableCampaign(Templated):
def __init__(self, link, campaign, transaction, is_pending, is_live,
is_complete):
self.link = link
self.campaign = campaign
self.spent = promote.get_spent_amount(campaign)
self.paid = bool(transaction and not transaction.is_void())
self.free = campaign.is_freebie()
self.is_pending = is_pending
self.is_live = is_live
self.is_complete = is_complete
self.needs_refund = (is_complete and c.user_is_sponsor and
not transaction.is_refund() and
self.spent < campaign.bid)
self.pay_url = promote.pay_url(link, campaign)
self.view_live_url = promote.view_live_url(link, campaign.sr_name)
self.refund_url = promote.refund_url(link, campaign)
Templated.__init__(self)
@classmethod
def from_campaigns(cls, link, campaigns):
campaigns, is_single = tup(campaigns, ret_is_single=True)
transactions = promote.get_transactions(link, campaigns)
live_campaigns = promote.live_campaigns_by_link(link)
today = promote.promo_datetime_now().date()
ret = []
for camp in campaigns:
transaction = transactions.get(camp._id)
is_pending = today < to_date(camp.start_date)
is_live = camp in live_campaigns
is_complete = (transaction and (transaction.is_charged() or
transaction.is_refund()) and
not (is_live or is_pending))
rc = cls(link, camp, transaction, is_pending, is_live, is_complete)
ret.append(rc)
if is_single:
return ret[0]
else:
return ret
def render_html(self):
return spaceCompress(self.render(style='html'))
class RefundPage(Reddit):
def __init__(self, link, campaign):
self.link = link
@@ -3783,7 +3828,14 @@ class MediaEmbedBody(CachedTemplate):
class PaymentForm(Templated):
def __init__(self, link, campaign, **kw):
self.link = link
self.campaign = promote.get_renderable_campaigns(link, campaign)
self.duration = strings.time_label
self.duration %= {'num': campaign.ndays,
'time': ungettext("day", "days", campaign.ndays)}
self.start_date = campaign.start_date.strftime("%m/%d/%Y")
self.end_date = campaign.end_date.strftime("%m/%d/%Y")
self.campaign_id36 = campaign._id36
self.budget = format_currency(float(campaign.bid), 'USD',
locale=c.locale)
Templated.__init__(self, **kw)
class Promotion_Summary(Templated):

View File

@@ -46,7 +46,7 @@ from r2.lib.cache import sgm
from r2.lib.memoize import memoize
from r2.lib.strings import strings
from r2.lib.template_helpers import get_domain
from r2.lib.utils import tup, to_date, weighted_lottery
from r2.lib.utils import to_date, weighted_lottery
from r2.models import (
Account,
Bid,
@@ -154,87 +154,6 @@ def is_live_on_sr(link, sr):
return bool(live_campaigns_by_link(link, sr=sr))
# control functions
class RenderableCampaign():
def __init__(self, campaign_id36, start_date, end_date, duration, bid,
spent, cpm, sr, priority, status):
self.campaign_id36 = campaign_id36
self.start_date = start_date
self.end_date = end_date
self.duration = duration
if priority.cpm:
self.bid = "%.2f" % bid
self.spent = "%.2f" % spent
else:
self.bid = "N/A"
self.spent = "N/A"
self.cpm = cpm
self.sr = sr
self.priority_name = priority.name
self.inventory_override = ("override" if priority.inventory_override
else "")
self.status = status
@classmethod
def create(cls, link, campaigns):
transactions = get_transactions(link, campaigns)
live_campaigns = live_campaigns_by_link(link)
user_is_sponsor = c.user_is_sponsor
today = promo_datetime_now().date()
r = []
for camp in campaigns:
transaction = transactions.get(camp._id)
campaign_id36 = camp._id36
start_date = camp.start_date.strftime("%m/%d/%Y")
end_date = camp.end_date.strftime("%m/%d/%Y")
ndays = camp.ndays
duration = strings.time_label % dict(num=ndays,
time=ungettext("day", "days", ndays))
bid = camp.bid
spent = get_spent_amount(camp)
cpm = getattr(camp, 'cpm', g.cpm_selfserve.pennies)
sr = camp.sr_name
live = camp in live_campaigns
pending = today < to_date(camp.start_date)
complete = (transaction and (transaction.is_charged() or
transaction.is_refund()) and
not (live or pending))
status = {'paid': bool(transaction),
'complete': complete,
'free': camp.is_freebie(),
'pay_url': pay_url(link, camp),
'view_live_url': view_live_url(link, sr),
'sponsor': user_is_sponsor,
'live': live,
'non_cpm': not camp.priority.cpm}
if transaction and transaction.is_void():
status['paid'] = False
status['free'] = False
if complete and user_is_sponsor and not transaction.is_refund():
if spent < bid:
status['refund'] = True
status['refund_url'] = refund_url(link, camp)
rc = cls(campaign_id36, start_date, end_date, duration, bid, spent,
cpm, sr, camp.priority, status)
r.append(rc)
return r
def get_renderable_campaigns(link, campaigns):
campaigns, is_single = tup(campaigns, ret_is_single=True)
r = RenderableCampaign.create(link, campaigns)
if is_single:
r = r[0]
return r
# These could be done with relationships, but that seeks overkill as
# we never query based on user and only check per-thing
def is_traffic_viewer(thing, user):

View File

@@ -4666,12 +4666,16 @@ ul.tabmenu.formtab {
border: none;
}
.existing-campaigns td.bid {
.existing-campaigns td.campaign-bid {
background: none no-repeat scroll center right;
padding-right: 15px;
.bid-amount {
display: block;
}
}
.existing-campaigns td.bid.paid {
.existing-campaigns td.campaign-bid.paid {
background-image: url(../green-check.png);
}
@@ -4680,8 +4684,9 @@ ul.tabmenu.formtab {
font-weight: bold;
}
.existing-campaigns td.bid .info{
.existing-campaigns td.campaign-bid .info{
margin-right: 3px;
margin-left: 3px;
}
.prefright p.minimum-spend {

View File

@@ -1,14 +1,16 @@
r.sponsored = {
init: function(isSponsor) {
init: function() {
$("#sr-autocomplete").on("sr-changed blur", function() {
r.sponsored.fill_campaign_editor()
})
this.isSponsor = isSponsor
this.inventory = {}
},
setup: function(inventory_by_sr) {
setup: function(inventory_by_sr, isEmpty) {
this.inventory = inventory_by_sr
if (isEmpty) {
this.fill_campaign_editor()
}
},
get_dates: function(startdate, enddate) {
@@ -65,34 +67,35 @@ r.sponsored = {
},
get_booked_inventory: function($form, srname, isOverride) {
var campaign_id36 = $form.find('input[name="campaign_id36"]').val(),
campaign_row = $('.existing-campaigns .campaign-row input[name="campaign_id36"]')
.filter('*[value="' + campaign_id36 + '"]')
.parents("tr")
if (!campaign_row.length) {
var campaign_name = $form.find('input[name="campaign_name"]').val()
if (!campaign_name) {
return {}
}
if (!campaign_row.hasClass('paid')) {
var $campaign_row = $('.existing-campaigns .' + campaign_name)
if (!$campaign_row.length) {
return {}
}
var existing_srname = campaign_row.find('*[name="targeting"]').val()
if (!$campaign_row.data('paid')) {
return {}
}
var existing_srname = $campaign_row.data("targeting")
if (srname != existing_srname) {
return {}
}
var existingOverride = campaign_row.find('*[name="override"]').val() == "override"
var existingOverride = $campaign_row.data("override")
if (isOverride != existingOverride) {
return {}
}
var startdate = campaign_row.find('*[name="startdate"]').val(),
enddate = campaign_row.find('*[name="enddate"]').val(),
var startdate = $campaign_row.data("startdate"),
enddate = $campaign_row.data("enddate"),
dates = this.get_dates(startdate, enddate),
bid = campaign_row.find('*[name="bid"]').val(),
cpm = campaign_row.find('*[name="cpm"]').val(),
bid = $campaign_row.data("bid"),
cpm = $campaign_row.data("cpm"),
ndays = this.duration_from_dates(startdate, enddate),
impressions = this.calc_impressions(bid, cpm),
daily = Math.floor(impressions / ndays),
@@ -230,9 +233,9 @@ r.sponsored = {
cpm = this.get_cpm($form),
ndays = this.get_duration($form),
impressions = this.calc_impressions(bid, cpm),
selected = $form.find('*[name="priority"]:checked'),
isOverride = selected.attr("override") == "override",
isCpm = selected.attr("cpm") == "cpm"
priority = $form.find('*[name="priority"]:checked'),
isOverride = priority.data("override"),
isCpm = priority.data("cpm")
$(".duration").text(ndays + " " + ((ndays > 1) ? r._("days") : r._("day")))
$(".price-info").text(r._("$%(cpm)s per 1,000 impressions").format({cpm: (cpm/100).toFixed(2)}))
@@ -375,172 +378,28 @@ function check_enddate(startdate, enddate) {
$("#datepicker-" + enddate.attr("id")).datepicker("destroy");
}
(function($) {
$.update_campaign = function(campaign_name, campaign_html) {
cancel_edit(function() {
var $existing = $('.existing-campaigns .' + campaign_name),
tableWasEmpty = $('.existing-campaigns table tr.campaign-row').length == 0
function get_flag_class(flags) {
var css_class = "campaign-row";
if(flags.free) {
css_class += " free";
}
if(flags.live) {
css_class += " live";
}
if(flags.complete) {
css_class += " complete";
}
else if (flags.paid) {
css_class += " paid";
}
if (flags.sponsor) {
css_class += " sponsor";
}
if (flags.refund) {
css_class += " refund";
}
if (flags.non_cpm) {
css_class += " non_cpm";
}
return css_class
}
$.new_campaign = function(campaign_id36, start_date, end_date, duration,
bid, spent, cpm, targeting, priority, override, flags) {
cancel_edit(function() {
var data =('<input type="hidden" name="startdate" value="' +
start_date +'"/>' +
'<input type="hidden" name="enddate" value="' +
end_date + '"/>' +
'<input type="hidden" name="bid" value="' + bid + '"/>' +
'<input type="hidden" name="cpm" value="' + cpm + '"/>' +
'<input type="hidden" name="targeting" value="' +
(targeting || '') + '"/>' +
'<input type="hidden" name="priority" value="' + priority + '"/>' +
'<input type="hidden" name="override" value="' + override + '"/>' +
'<input type="hidden" name="campaign_id36" value="' + campaign_id36 + '"/>');
if (flags && flags.pay_url) {
data += ("<input type='hidden' name='pay_url' value='" +
flags.pay_url + "'/>");
}
if (flags && flags.view_live_url) {
data += ("<input type='hidden' name='view_live_url' value='" +
flags.view_live_url + "'/>");
}
if (flags && flags.refund_url) {
data += ("<input type='hidden' name='refund_url' value='" +
flags.refund_url + "'/>");
}
var row = [start_date, end_date, duration, priority, "$" + bid, "$" + spent, targeting, data];
$(".existing-campaigns .error").hide();
var css_class = get_flag_class(flags);
$(".existing-campaigns table").show()
.insert_table_rows([{"id": "", "css_class": css_class,
"cells": row}], -1);
check_number_of_campaigns();
$.set_up_campaigns()
});
return $;
};
$.update_campaign = function(campaign_id36, start_date, end_date,
duration, bid, spent, cpm, targeting, priority,
override, flags) {
cancel_edit(function() {
$('.existing-campaigns input[name="campaign_id36"]')
.filter('*[value="' + (campaign_id36 || '0') + '"]')
.parents("tr").removeClass()
.addClass(get_flag_class(flags))
.children(":first").html(start_date)
.next().html(end_date)
.next().html(duration)
.next().html(priority)
.next().html("$" + bid).removeClass()
.next().html("$" + spent)
.next().html(targeting)
.next()
.find('*[name="startdate"]').val(start_date).end()
.find('*[name="enddate"]').val(end_date).end()
.find('*[name="targeting"]').val(targeting).end()
.find('*[name="priority"]').val(priority).end()
.find('*[name="override"]').val(override).end()
.find('*[name="bid"]').val(bid).end()
.find('*[name="cpm"]').val(cpm).end()
.find("button, span").remove();
$.set_up_campaigns();
});
};
$.set_up_campaigns = function() {
var edit = "<button>edit</button>";
var del = "<button>delete</button>";
var pay = "<button>pay</button>";
var free = "<button>free</button>";
var repay = "<button>change</button>";
var view = "<button>view live</button>";
var refund = "<button>refund</button>";
$(".existing-campaigns tr").each(function() {
var tr = $(this);
var td = $(this).find("td:last");
var bid_td = $(this).find("td:first").next().next().next().next()
.addClass("bid");
if(td.length && ! td.children("button, span").length ) {
if(tr.hasClass("live")) {
$(td).append($(view).addClass("view fancybutton")
.click(function() { view_campaign(tr) }));
}
if (tr.hasClass('refund')) {
$(bid_td).append($(refund).addClass("refund fancybutton")
.click(function() { refund_campaign(tr) }));
}
/* once paid, we shouldn't muck around with the campaign */
if(!tr.hasClass("complete") && !tr.hasClass("live")) {
if (!tr.hasClass("non_cpm")) {
if (tr.hasClass("sponsor") && !tr.hasClass("free")) {
$(bid_td).append($(free).addClass("free")
.click(function() { free_campaign(tr) }))
}
else if (!tr.hasClass("paid")) {
$(bid_td).prepend($(pay).addClass("pay fancybutton")
.click(function() { pay_campaign(tr) }));
} else if (tr.hasClass("free")) {
$(bid_td).addClass("free paid")
.prepend("<span class='info'>freebie</span>");
} else {
(bid_td).addClass("paid")
.prepend($(repay).addClass("pay fancybutton")
.click(function() { pay_campaign(tr) }));
}
}
var e = $(edit).addClass("edit fancybutton")
.click(function() { edit_campaign(tr); });
var d = $(del).addClass("d fancybutton")
.click(function() { del_campaign(tr); });
$(td).append(e).append(d);
} else {
if (tr.hasClass("complete")) {
$(td).append("<span class='info'>complete</span>");
}
if (!tr.hasClass("non_cpm")) {
$(bid_td).addClass("paid")
}
/* sponsors can always edit */
if (tr.hasClass("sponsor")) {
var e = $(edit).addClass("edit fancybutton")
.click(function() { edit_campaign(tr); });
$(td).append(e);
}
}
if ($existing.length) {
$existing.replaceWith(campaign_html)
$existing.fadeIn()
} else {
$(campaign_html).hide()
.insertAfter('.existing-campaigns tr:last')
.css('display', 'table-row')
.fadeIn()
}
});
if (!r.sponsored.isSponsor) {
$('.existing-campaigns tr td:nth-child(4), .existing-campaigns tr th:nth-child(4)').hide()
if (tableWasEmpty) {
$('.existing-campaigns p.error').hide()
$('.existing-campaigns table').fadeIn()
}
})
}
return $;
}
}(jQuery));
function detach_campaign_form() {
@@ -584,72 +443,70 @@ function cancel_edit(callback) {
}
}
function del_campaign(elem) {
var campaign_id36 = $(elem).find('*[name="campaign_id36"]').val();
var link_id = $("#campaign").find('*[name="link_id"]').val();
function del_campaign($campaign_row) {
var link_id = $("#campaign").find('*[name="link_id"]').val(),
campaign_id36 = $campaign_row.data('campaign_id36')
$.request("delete_campaign", {"campaign_id36": campaign_id36,
"link_id": link_id},
null, true, "json", false);
$(elem).children(":first").delete_table_row(check_number_of_campaigns);
$campaign_row.children(":first").delete_table_row(check_number_of_campaigns);
}
function edit_campaign(elem) {
/* find the table row in question */
var tr = $(elem).get(0);
function edit_campaign($campaign_row) {
cancel_edit(function() {
var campaign = detach_campaign_form()
if ($("#campaign").parents('tr:first').get(0) != tr) {
$(".existing-campaigns table")
.insert_table_rows([{
"id": "edit-campaign-tr",
"css_class": "",
"cells": [""]
}], $campaign_row.get(0).rowIndex + 1)
cancel_edit(function() {
var editRow = $("#edit-campaign-tr")
editRow.children('td:first').attr("colspan", 8).append(campaign)
$campaign_row.fadeOut(function() {
/* fill inputs from data in campaign row */
$.map(['startdate', 'enddate', 'bid', 'cpm', 'campaign_id36', 'campaign_name'],
function(input) {
var val = $campaign_row.data(input),
$input = campaign.find('*[name="' + input + '"]')
$input.val(val)
})
/* copy the campaign element */
var campaign = detach_campaign_form();
/* set priority */
var priorities = campaign.find('*[name="priority"]'),
campPriority = $campaign_row.data("priority")
$(".existing-campaigns table")
.insert_table_rows([{"id": "edit-campaign-tr",
"css_class": "", "cells": [""]}],
tr.rowIndex + 1);
$("#edit-campaign-tr").children('td:first')
.attr("colspan", 8).append(campaign).end()
.prev().fadeOut(function() {
var data_tr = $(this);
var c = $("#campaign");
$.map(['startdate', 'enddate', 'bid', 'cpm', 'campaign_id36'],
function(i) {
i = '*[name="' + i + '"]';
c.find(i).val(data_tr.find(i).val());
});
var priorities = c.find('*[name="priority"]'),
campPriority = data_tr.find('*[name="priority"]').val()
priorities.filter('*[value="' + campPriority + '"]')
.prop("checked", "checked")
/* check if targeting is turned on */
var targeting = data_tr
.find('*[name="targeting"]').val();
var radios=c.find('*[name="targeting"]');
if (targeting) {
radios.filter('*[value="one"]')
.prop("checked", "checked");
c.find('*[name="sr"]').val(targeting).prop("disabled", "").end()
.find(".targeting").show();
}
else {
radios.filter('*[value="none"]')
.prop("checked", "checked");
c.find('*[name="sr"]').val("").prop("disabled", "disabled").end()
.find(".targeting").hide();
}
/* attach the dates to the date widgets */
init_startdate();
init_enddate();
c.find('button[name="save"]').show().end()
.find('button[name="create"]').hide().end();
r.sponsored.fill_campaign_editor();
c.fadeIn();
} );
priorities.filter('*[value="' + campPriority + '"]')
.prop("checked", "checked")
/* check if targeting is turned on */
var targeting = $campaign_row.data("targeting"),
radios = campaign.find('*[name="targeting"]');
if (targeting) {
radios.filter('*[value="one"]')
.prop("checked", "checked");
campaign.find('*[name="sr"]').val(targeting).prop("disabled", "").end()
.find(".targeting").show();
} else {
radios.filter('*[value="none"]')
.prop("checked", "checked");
campaign.find('*[name="sr"]').val("").prop("disabled", "disabled").end()
.find(".targeting").hide();
}
);
}
/* attach the dates to the date widgets */
init_startdate();
init_enddate();
campaign.find('button[name="save"]').show().end()
.find('button[name="create"]').hide().end();
r.sponsored.fill_campaign_editor();
campaign.fadeIn();
})
})
}
function check_number_of_campaigns(){
@@ -669,17 +526,20 @@ function create_campaign() {
return;
}
cancel_edit(function() {;
var base_cpm = $("#bid").data("base_cpm")
var base_cpm = $("#bid").data("base_cpm"),
minBid = $("#bid").data("min_bid")
init_startdate();
init_enddate();
$("#campaign")
.find('button[name="edit"]').hide().end()
.find('button[name="save"]').hide().end()
.find('button[name="create"]').show().end()
.find('input[name="campaign_id36"]').val('').end()
.find('input[name="campaign_name"]').val('').end()
.find('input[name="sr"]').val('').prop("disabled", "disabled").end()
.find('input[name="targeting"][value="none"]').prop("checked", "checked").end()
.find('input[name="priority"][default="default"]').prop("checked", "checked").end()
.find('input[name="bid"]').val($("#bid").data("min_bid") * 5).end()
.find('input[name="priority"][data-default="true"]').prop("checked", "checked").end()
.find('input[name="bid"]').val(minBid * 5).end()
.find(".targeting").hide().end()
.find('input[name="cpm"]').val(base_cpm).end()
.fadeIn();
@@ -687,23 +547,11 @@ function create_campaign() {
});
}
function free_campaign(elem) {
var campaign_id36 = $(elem).find('*[name="campaign_id36"]').val();
var link_id = $("#campaign").find('*[name="link_id"]').val();
function free_campaign($campaign_row) {
var link_id = $("#campaign").find('*[name="link_id"]').val(),
campaign_id36 = $campaign_row.data('campaign_id36')
$.request("freebie", {"campaign_id36": campaign_id36, "link_id": link_id},
null, true, "json", false);
$(elem).find(".free").fadeOut();
$campaign_row.find(".free").fadeOut();
return false;
}
function pay_campaign(elem) {
$.redirect($(elem).find('input[name="pay_url"]').val());
}
function view_campaign(elem) {
$.redirect($(elem).find('input[name="view_live_url"]').val());
}
function refund_campaign(elem) {
$.redirect($(elem).find('input[name="refund_url"]').val());
}

View File

@@ -20,29 +20,21 @@
## reddit Inc. All Rights Reserved.
###############################################################################
<%!
from babel.numbers import format_currency
from r2.lib.template_helpers import static
from r2.lib import js
%>
<%namespace file="utils.html" import="error_field"/>
${unsafe(js.use('sponsored'))}
<div class="payment-setup">
<h1>${_("set up payment for this link")}</h1>
<form method="POST" action="/post/pay" id="pay-form"
class="pretty-form"
onsubmit="return post_form(this, 'update_pay')">
<p>
The duration of this link is ${thing.campaign.duration}
(from ${thing.campaign.start_date} to ${thing.campaign.end_date}).
The duration of this link is ${thing.duration}
(from ${thing.start_date} to ${thing.end_date}).
</p>
<p id="bid-field">
<input type="hidden" name="campaign" value="${thing.campaign.campaign_id36}" />
<input type="hidden" name="campaign" value="${thing.campaign_id36}" />
<input type="hidden" name="link" value="${thing.link._fullname}" />
<% budget=format_currency(float(thing.campaign.bid), 'USD', locale=c.locale) %>
${unsafe(_("Your current budget is %(budget)s") % dict(budget=budget))}
${unsafe(_("Your current budget is %(budget)s") % dict(budget=thing.budget))}
${error_field("OVERSOLD_DETAIL", "bid", "div")}
</p>
%if thing.profiles:
@@ -80,9 +72,6 @@ ${unsafe(js.use('sponsored'))}
</form>
<script type="text/javascript">
function cancel_enable_all(elem) {
}
function enable_all(elem) {
$(elem).parents("div.pay-form").andSelf()
.find("[disabled]").removeAttr("disabled").end()

View File

@@ -42,8 +42,10 @@ ${unsafe(js.use('sponsored'))}
<%def name="javascript_setup()">
<script type="text/javascript">
r.sponsored.init(${unsafe(simplejson.dumps(c.user_is_sponsor))});
r.sponsored.setup(${unsafe(simplejson.dumps(thing.inventory))})
r.sponsored.init();
r.sponsored.setup(${unsafe(simplejson.dumps(thing.inventory))},
${simplejson.dumps(not thing.campaigns)})
</script>
</%def>
@@ -227,7 +229,7 @@ ${self.javascript_setup()}
<br />
</div>
<div class="infotext rounded">
<div class="help infotext rounded">
<p>${_("Comments are a great way to get feedback from customers, and the reddit community is known for being vocal in comment threads.")}</p>
</div>
</%utils:line_field>
@@ -347,15 +349,15 @@ ${self.javascript_setup()}
<tr style="${'display:none' if not c.user_is_sponsor else ''}">
<th>${_("priority")}</th>
<td class="prefright">
%for value, text, description, default, inventory_override, cpm in thing.priorities:
%for value, text, description, default, override, cpm in thing.priorities:
<label>
<input id="${value}" class="nomargin"
type="radio" value="${value}" name="priority"
onclick="r.sponsored.priority_changed()"
${"checked='checked'" if default else ""}
${"default='default'" if default else ""}
${"override='override'" if inventory_override else ""}
${"cpm='cpm'" if cpm else ""}>
data-default="${simplejson.dumps(default)}"
data-override="${simplejson.dumps(override)}"
data-cpm="${simplejson.dumps(cpm)}">
%if description:
<span>${"%s (%s)" % (text, description)}</span>
%else:
@@ -414,18 +416,6 @@ ${self.javascript_setup()}
onclick="r.sponsored.targeting_on()">
${_("targeted (targets a subreddit and its subscribers)")}
</label>
<script type="text/javascript">
$(function() {
var c = $(".campaign input[name=targeting]:checked");
if (c.val() == 'one') {
r.sponsored.targeting_on();
} else {
r.sponsored.targeting_off();
}
})
</script>
</td>
</tr>
</table>
@@ -453,7 +443,8 @@ ${self.javascript_setup()}
</div>
<div class="buttons">
<input type="hidden" name="campaign_id36" value="" />
<input type="hidden" name="campaign_id36" value="">
<input type="hidden" name="campaign_name" value="">
<span class="status error"></span>
<button name="cancel"
onclick="return cancel_edit()" class="fancybutton">
@@ -492,7 +483,9 @@ ${self.javascript_setup()}
<th title="${start_title}">${_("start")}</th>
<th title="${end_title}">${_("end")}</th>
<th>${_("duration")}</th>
<th>${_("priority")}</th>
<th style="${'display:none' if not c.user_is_sponsor else ''}">
${_("priority")}
</th>
<th>${_("total budget")}</th>
<th>${_("spent")}</th>
<th title="${targeting_title}">${_("targeting")}</th>
@@ -503,20 +496,11 @@ ${self.javascript_setup()}
onclick="return create_campaign()">+ add new</button>
</th>
</tr>
%for camp in thing.campaigns:
${camp}
%endfor
</table>
<script type="text/javascript">
$(function() {
%for rc in sorted(thing.campaigns, key=lambda rc: rc.start_date):
$.new_campaign(${unsafe(','.join(simplejson.dumps(attr) for attr in
[rc.campaign_id36, rc.start_date, rc.end_date, rc.duration,
rc.bid, rc.spent, rc.cpm, rc.sr, rc.priority_name,
rc.inventory_override, rc.status]))});
%endfor
$.set_up_campaigns();
});
</script>
<p class="error"
style="${'display:none' if thing.campaigns else ''}">
${_("You don't have any campaigns for this link yet. You should add one.")}

View File

@@ -0,0 +1,131 @@
## The contents of this file are subject to the Common Public Attribution
## License Version 1.0. (the "License"); you may not use this file except in
## compliance with the License. You may obtain a copy of the License at
## http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
## License Version 1.1, but Sections 14 and 15 have been added to cover use of
## software over a computer network and provide for limited attribution for the
## Original Developer. In addition, Exhibit A has been modified to be
## consistent with Exhibit B.
##
## Software distributed under the License is distributed on an "AS IS" basis,
## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
## the specific language governing rights and limitations under the License.
##
## The Original Code is reddit.
##
## The Original Developer is the Initial Developer. The Initial Developer of
## the Original Code is reddit Inc.
##
## All portions of the code written by reddit are Copyright (c) 2006-2013
## reddit Inc. All Rights Reserved.
###############################################################################
<%!
import json
from r2.lib.strings import strings
from babel.numbers import format_currency
%>
<% jquery_row = "$('." + thing.campaign._fullname + "')" %>
<tr class="campaign-row ${thing.campaign._fullname} ${'refund' if thing.needs_refund else ''}"
data-startdate="${thing.campaign.start_date.strftime('%m/%d/%Y')}"
data-enddate="${thing.campaign.end_date.strftime('%m/%d/%Y')}"
data-bid="${'%.2f' % thing.campaign.bid}"
data-targeting="${thing.campaign.sr_name}"
data-cpm="${getattr(thing.campaign, 'cpm', g.cpm_selfserve.pennies)}"
data-campaign_id36="${thing.campaign._id36}"
data-campaign_name="${thing.campaign._fullname}"
data-priority="${thing.campaign.priority.name}"
data-override="${json.dumps(thing.campaign.priority.inventory_override)}"
data-paid="${json.dumps(thing.paid)}">
<td class="campaign-start-date">
${thing.campaign.start_date.strftime("%m/%d/%Y")}
</td>
<td class="campaign-end-date">
${thing.campaign.end_date.strftime("%m/%d/%Y")}
</td>
<td class="campaign-duration">
${strings.time_label % dict(num=thing.campaign.ndays,
time=ungettext("day", "days", thing.campaign.ndays))}
</td>
<td class="campaign-priority"
style="${'display:none' if not c.user_is_sponsor else ''}">
${thing.campaign.priority.text}
</td>
<td class="campaign-bid ${'paid' if thing.paid else ''}">
<div class="bid-amount">
%if thing.campaign.priority.cpm:
${format_currency(thing.campaign.bid, 'USD', locale=c.locale)}
%else:
${_("N/A")}
%endif
</div>
%if thing.campaign.priority.cpm:
%if not thing.paid:
%if c.user_is_sponsor:
<button class="free fancybutton" onclick="free_campaign(${jquery_row})">
${_("free")}
</button>
%else:
<button class="pay fancybutton" onclick="$.redirect('${thing.pay_url}')">
${_("pay")}
</button>
%endif
%elif not (thing.is_complete or thing.is_live):
<button class="pay fancybutton" onclick="$.redirect('${thing.pay_url}')">
${_("change")}
</button>
%elif thing.free:
<span class='info'>${_("freebie")}</span>
%endif
%endif
%if not thing.free and c.user_is_sponsor and thing.needs_refund:
<button class="refund fancybutton" onclick="$.redirect('${thing.refund_url}')">
${_("refund")}
</button>
%endif
</td>
<td class="campaign-spent">
%if thing.campaign.priority.cpm:
${format_currency(thing.spent, 'USD', locale=c.locale)}
%else:
${_("N/A")}
%endif
</td>
<td class="campaign-target">
${'/r/%s' % thing.campaign.sr_name if thing.campaign.sr_name else _('frontpage')}
</td>
<td class="campaign-buttons">
%if thing.is_complete:
<span class='info'>${_("complete")}</span>
%else:
%if not thing.is_live or c.user_is_sponsor:
<button class="edit fancybutton" onclick="edit_campaign(${jquery_row})">
${_("edit")}
</button>
%endif
%if not thing.is_live:
<button class="delete fancybutton" onclick="del_campaign(${jquery_row})">
${_("delete")}
</button>
%endif
%if thing.is_live:
<button class="view fancybutton" onclick="$.redirect('${thing.view_live_url}')">
${_("view live")}
</button>
%endif
%endif
</td>
</tr>