Controllers.prototype.campaigns = (function(){
'use strict';
function newCampaigns(c, t, d, rcb){ return new Campaigns(c,t,d,rcb); }
var Campaigns = function(core, target, data, returnCB){
var template = new Template(),
rendered = render(template.index, null),
element = getElementFromString(rendered),
events = new EventManager(),
actions = null,
table = null,
elements = null,
reportingData = null,
spentData = null,
schedDlg = new ReportDialog('sched'),
period = '7';
this.exit = exit;
this.search = search;
new ApiManager({
'campaignsList' : null,
'reporting' : {args: period + '?noAds=true'},
'campaignsSpent': {args: period},
'campaignDrafts' : null
}, core.userID, init);
function init(error, d){
spentData = d.campaignsSpent || {};
if(returnCB) returnCB();
setControllerVariables(d);
initMain(error, d);
bindActionAnchors();
insertElement();
}
function initMain(e, d){ initHeader(); if(isValidData(d.campaignsList) || isValidData(d.campaignDrafts)) initDefault(d); else initFresh(); }
function initDefault(d){ initTable(d.reporting); initStats(); }
function initFresh(){ elements.fresh = getElementFromString(template.fresh); hideManage(); data.table.rows = []; element.appendChild(elements.fresh); }
function initTable(reporting){
table = NewMTable(element.querySelector('.manageTable'), processTableData(data.table, reporting), tableUpdate);
tableUpdate();
}
function initHeader(){
elements.createCampaign = element.querySelector('a.createCampaign');
elements.createDomainLists = element.querySelector('a.createDomainLists');
events.add(elements.createCampaign, 'click', popAnchor);
events.add(elements.createDomainLists, 'click', popAnchor);
}
function initStats(){
elements.stats = new Dropdown(element.querySelector('.stats'), data.stats, reloadStats);
elements.stats.setByValue('7');
}
function search(v){ table.search('name', v.target.value); }
function isValidData(d){ return isDefined(d) && d.length > 0; }
function Template(){
var header = '',
edit = 'Edit',
dup = 'Copy',
del = '',
reports = '',
share = 'Share',
stats = '',
manageRow = '
Manage Campaigns
'+ edit + dup + del + reports +
share + stats + ' ',
manageTable = '';
this.index = '' + header + manageRow + manageTable + '
';
this.fresh = 'Oh no! It appears that we have no campaigns here. We should add some. Try it out - it\'s simple!
';
}
function dupAction(e) {
var row = getSelectedRow(),
id = row.id;
pD(e);
ga('send', 'event', 'Campaigns', 'Duplicate', id);
apiRequest('GET', 'campaigns/byCID', id, null, function(data, status) {
if(!data) return console.warn(status, data);
if(!data.success || data.error) return core.notifications.setError(data.error);
var cmp = data.data;
delete cmp.id;
cmp.name += ' (Duplicate)';
return apiRequest('POST', 'campaignDrafts', core.userID, cmp, function(data, status) {
if(!data) return console.warn(status, data);
if(!data.success || data.error) return core.notifications.setError(data.error);
return pop('Pop!', 'Campaigns - Edit', '/dashboard/campaignDraft/' + data.id);
});
});
}
function editAction(e){
var row = getSelectedRow(),
id = row.id;
pD(e);
ga('send', 'event', 'Campaigns', 'Edit', id);
if(row.isDraft){
pop('Pop!', 'Campaigns - Edit', '/dashboard/campaignDraft/' + id);
return;
}
pop('Pop!', 'Campaigns - Edit', '/dashboard/campaigns/edit/' + id);
}
function delAction(e){
var rows = table.getSelectedRows(),
items = [],
cids = [],
dids = [];
pD(e);
loop(rows, p);
new ApiReqGroup(items, updateActionCB);
if(cids.length > 0){
ga('send', 'event', 'Campaigns', 'Delete', getIDArray(cids).join(', '));
}
if(dids.length > 0){
ga('send', 'event', 'Campaign Drafts', 'Delete', getIDArray(dids).join(', '));
}
function p(k, v){
var d = v.getData(),
url = !d.isDraft ? '/api/v1/campaigns/byCID/' : '/api/v1/campaignDraft/';
items[k] = new ApiReqItem('DELETE', url + d.id, null);
}
}
function shareAction(e){
var id = getSelectedRow().id;
pD(e);
ga('send', 'event', 'Campaigns', 'Share', id);
pop('Pop!', 'Campaigns - Share', '/dashboard/campaigns/share/create/' + id);
}
function updateActionCB(e){
if(e && e.length && e[0].error && e[0].message) new core.notifications.setError(e[0].message);
getCampaignsList(updateCampaignsList);
}
function updateCampaignsList(e, o){ data.table.rows = getCampaigns(o.campaignsList, o.campaignDrafts); refreshTable(); }
function getSelectedRow(){ return table.getSelectedRows()[0].getData(); }
function getCampaignsList(cb){ new ApiManager({ 'campaignsList' : null, 'campaignDrafts' : null }, core.userID, cb); }
function reloadStats(p) {
core.notifications.setLoading();
period = p;
new ApiManager({'reporting' : {'args': period + '?noAds=true'}, 'campaignsSpent': {args: p}}, core.userID, updateStats);
}
function updateStats(err, d) {
spentData = d.campaignsSpent || {};
refreshTable(d);
core.notifications.setSuccess('w00t!');
}
function setControllerVariables(d){
var reports = element.querySelector('.reports');
data = new Data(d.campaignsList, d.campaignDrafts);
reportingData = d.reporting;
actions = element.querySelector('actions');
elements = new Elements(element, {
'edit' : { 'target' : actions.querySelector('.edit') },
'del' : {
'target' : new ConfirmationButton(actions.querySelector('.delete'), {
'color' : 'hot',
'text' : 'Delete',
'className' : 'tidySmall',
'confirmColor' : 'mist',
'confirmText' : 'Confirm?'
}, delAction)
},
'dup': { 'target' : actions.querySelector('.dup') },
'reports': { 'target' : reports },
'reportsDd' : { 'target' : new Dropdown(reports, data.getReport, setReportModal) },
'share' : { 'target' : actions.querySelector('.share') },
'stats' : {},
'fresh' : {},
'createCampaignOptions' : {},
'modal' : {}
});
}
function setReportModal(e){
if(!e) return;
var ids = getIDArray(getCampaignRows(table));
if(e === 'sched') {
schedDlg.show(null, function(data, canceled) {
if(canceled) return true;
promiseLoop(ids, function(_ , cid, done) {
new HttpRequest('POST', '/api/v1/scheduledReports/' + core.userID,
new scheduledReportOpts(core.userID, cid, 'campaign', data.frequency, data.format, data.recipient), 'json', 'json', function(v) { done(v.error); });
}, function(errs) {
if(!errs) return pop('Pop!', 'Downloads', '/dashboard/downloads');
core.notifications.setMissingFields(errs);
});
return true;
});
return;
}
if(!!elements.modal) elements.modal.exit();
elements.modal = new ReportModal(core, events, e, ids);
}
function tableUpdate(){
var bd = new RowsBreakdown(table);
if(bd.total > 0) enableActions(); else disableActions();
if(bd.total > 1){
elements.edit.classList.add('noDisplay');
elements.share.classList.add('noDisplay');
elements.dup.classList.add('noDisplay');
if(bd.campaigns > 0){
elements.reports.classList.remove('noDisplay');
}
} else {
elements.edit.classList.remove('noDisplay');
if(bd.campaigns > 0){
elements.share.classList.remove('noDisplay');
elements.reports.classList.remove('noDisplay');
elements.dup.classList.remove('noDisplay');
} else {
elements.share.classList.add('noDisplay');
elements.reports.classList.add('noDisplay');
elements.dup.classList.add('noDisplay');
}
}
elements.del.resetState();
}
function refreshTable(d){ if(table) table.exit(); initTable(!!d && !!d.reporting ? d.reporting : reportingData); }
function insertElement(){ target.appendChild(element); }
function bindActionAnchors(){
events.add(elements.edit, 'click', editAction);
events.add(elements.dup, 'click', dupAction);
events.add(elements.share, 'click', shareAction);
}
function hideManage(){ element.querySelector('.manageRow').classList.add('noDisplay'); }
function enableActions(){ actions.className = ''; }
function disableActions(){ actions.className = 'disabled'; }
function processTableData(t, reporting){
var c = getSimpleJSONCopy(t),
campaignReporting = getReportingByCampaign(reporting);
forEach(c.rows, r);
return c;
function r(t){
if(t.archived) {
t.status = 'Archived';
} else if (t.isDraft) {
t.status = 'Draft';
return;
} else if (t.active) {
t.status = 'On';
} else {
t.status = 'Off';
}
populateCampaignReporting(t, campaignReporting);
}
}
function getReportingByCampaign(reporting){
var campaignLevel = reporting.campaignLevel,
returnObj = {};
processDays(campaignLevel);
return returnObj;
function processDays(list){ for(var key in list){ processCampaigns(list[key], key); } }
function processCampaigns(list, key){
for(var date in list){
var t = list[date];
if(!isDefined(returnObj[key])) returnObj[key] = new CampaignReportingItem(key);
if(isDefined(t.impressions)) returnObj[key].impressions += t.impressions;
if(isDefined(t.clicks)) returnObj[key].clicks += t.clicks;
if(isDefined(t.vwis)) returnObj[key].vwis += t.vwis;
if(isDefined(t.conversions)) returnObj[key].conversions += t.conversions;
}
}
}
function populateCampaignReporting(t, campaignReporting){
var reportingItem = campaignReporting[t.id];
if(isDefined(reportingItem)){
t.impressions = reportingItem.impressions;
t.clicks = reportingItem.clicks;
t.conversions = reportingItem.conversions;
t.vwis = reportingItem.vwis;
t.spent = reportingItem.spent;
t.ctr = t.impressions > 0 ? ((t.clicks / t.impressions) * 100).toFixed(2) + '%' : '0%';
} else {
t.imps = 0;
t.clicks = 0;
t.vwis = 0;
t.conversions = 0;
t.spent = 0;
t.ctr = 0;
}
}
function CampaignReportingItem(id){
this.impressions = 0;
this.clicks = 0;
this.vwis = 0;
this.conversions = 0;
var spent = !!spentData[id] ? spentData[id].spent : 0;
this.spent = {title: fmtNum(spent), value: spent};
}
function pD(e){ if(isDefined(e) && isDefined(e.preventDefault)) e.preventDefault(); }
function exit(){ target.removeChild(element); events.reset(); if(table) removeTable(); if(elements) removeElements(); housekeeping(); }
function removeElements(){ elements.exit(); elements = null; }
function removeTable(){ table.exit(); table = null; }
function housekeeping(){ template = rendered = element = events = actions = table = elements = data = null; }
};
function Campaign(d, id, i, isDraft){
this.id = id;
this.displayOrder = i + 1;
this.active = getDataObjValue(d, 'active');
this.archived = getDataObjValue(d, 'archived');
this.isDraft = isDraft;
this.name = getDataObjValue(d, 'name');
this.notes = getDataObjValue(d, 'notes');
this.weeklyBudget = getDataObjValue(d, 'weeklyBudget');
this.unrestricted = getDataObjValue(d, 'unrestricted');
this.startDate = getDataObjValue(d, 'startDate');
this.endDate = getDataObjValue(d, 'endDate');
this.segments = getDataObjValue(d, 'segments');
this.adGroups = getDataObjValue(d, 'adGroups');
this.gender = getDataObjValue(d, 'gender');
this.ages = getDataObjValue(d, 'ages');
this.cities = getDataObjValue(d, 'cities');
this.dmas = getDataObjValue(d, 'dmas');
this.zipCodes = getDataObjValue(d, 'zipCodes');
this.contentCategory = getDataObjValue(d, 'contentCategory');
this.geography = getDataObjValue(d, 'geography');
this.clicks = d.clicks || 0;
this.vwis = d.vwis || 0;
this.conversions = d.conversions || 0;
this.impressions = d.impressions || 0;
this.baseCPM = getDataObjValue(d, 3);
}
function Data(list, drafts){
this.table = getTableObj(list, drafts);
this.createCmp = getCreateCmpObj();
this.getReport = getReportObj();
this.stats = getStatsObj();
}
function ReportModal(core, events, typ, ids){
var mdl = new Modal({ 'title' : 'Get report', 'contents' : getTmpl(), 'className' : 'overflow' }, exit),
downloadDropdownOpts = new DropdownObj([
{title: 'Download', value: '-', placeholder: true},
{title: 'Excel Spreadsheet', value: 'xlsx'},
{title: 'JSON', value: 'json'},
{title: 'CSV (zip)', value: 'zip'}
], '-', 'cool', 'cool', 'cool', true),
ele = mdl.element,
anchs = ele.querySelector('footer').querySelectorAll('a'),
fd = null,
td = null,
incDomains = false;
this.exit = exit;
events.add(anchs[0], 'click', exit, 'modal');
new Dropdown(ele.querySelector('footer').querySelector('div.download'), downloadDropdownOpts, action);
new CalendarInput(ele.querySelector('.sD'), null, function(e){
fd = getReportDateFmt(e.year, e.monthValue, e.date);
});
new CalendarInput(ele.querySelector('.eD'), null, function(e){
td = getReportDateFmt(e.year, e.monthValue, e.date);
});
new Checkbox(ele.querySelector('.incDomains'), function(v) { incDomains = v; });
function exit(e) {
preventDefault(e);
events.removeByTag('modal');
mdl.close();
}
function action(e){
if(e === '-') return;
if(e === undefined) return exit();
if(typ === 'report'){
new Reports(ids, fd, td, core, e, incDomains);
} else {
core.notifications.setError('Please enter an email address.');
return;
}
exit(e);
}
function getTmpl(){
var sD = 'Report start date:
',
eD = 'Report end date:
',
incD = 'Include Domains:
',
note = 'Note - Selecting multiple campaigns at a time may trigger your Pop-up blocking software if enabled. To avoid this, please disable your Pop-up blocker for https://' + core.brand.domain + '.
',
divs = '' + sD + eD + incD + note + '
',
dlDD = '',
footer = '';
return divs + footer;
}
}
function getReportDateFmt(year, month, date){ return year + '-' + forceDigits(month) + '-' + forceDigits(date); }
function forceDigits(v){ if(v > 9) return '' + v; else return '0' + v; }
function Reports(ids, fd, td, core, ext, incDomains){
ga('send', 'event', 'Campaigns', 'Download report', 'UID: ' + core.userID);
promiseLoop(ids, function(_ ,v, done){
new HttpRequest('GET', getSrc(v, fd, td, ext, incDomains), null, null, 'json', function(v) {
done(v.error);
});
}, function(errs) {
if(!errs) return pop('Pop!', 'Downloads', '/dashboard/downloads');
core.notifications.setMissingFields(errs);
});
function getSrc(id, fd, td, ext, incDomains) {
var url = '/api/v1/campaignReport/' + core.userID + '/' + id + '/' + fd + '/' + td + '/' + fd + '_' + td + '_report.' + ext;
if (!incDomains) url += '?noDomains=true';
return url;
}
}
function RowsBreakdown(tbl){
var c = 0,
d = 0;
loop(tbl.getSelectedRows(), p);
this.campaigns = c;
this.drafts = d;
this.total = c + d;
function p(k, v){
if(!v.getData().isDraft){
c++;
} else {
d++;
}
}
}
function getTableObj(list, drafts){
return {
'columns' : {
'#' : { 'title' : '#', 'valueType' : 'number', 'sortable' : true, 'width' : '72'},
'name' : { 'title' : 'Name', 'valueType' : 'string', 'sortable' : true, 'width' : '218' },
'status' : { 'title' : 'Status', 'valueType' : 'string', 'sortable' : true, 'width' : '80' },
'impressions' : { 'title' : 'Imps', 'valueType' : 'number', 'sortable' : true, 'width' : '102', 'formatType' : 'locale' },
'clicks' : { 'title' : 'Clicks', 'valueType' : 'number', 'sortable' : true, 'width' : '102', 'formatType' : 'locale' },
'conversions' : { 'title' : 'Pix Conv', 'valueType' : 'number', 'sortable' : true, 'width' : '94', 'formatType' : 'locale' },
'vwis' : { 'title' : 'Visits', 'valueType' : 'number', 'sortable' : true, 'width' : '102', 'formatType' : 'locale' },
'ctr' : { 'title' : 'CTR', 'valueType' : 'number', 'sortable' : true, 'width' : '80'},
'spent' : { 'title' : 'Spent', 'valueType' : 'number', 'sortable' : true, 'width' : '96'}
},
'rows' : getCampaigns(list, drafts),
'maxPerPage' : 10
};
}
function getCreateCmpObj(){
return {
'data' : [
{ 'title' : 'Create Campaign' },
{ 'title' : 'Web, Mobile, Native', 'href' : '/dashboard/campaigns/create', 'value' : 'advancedCampaign' }
],
'options' : { 'dropdownClass' : 'cool', 'menuItemClass' : 'cool', 'carrotClass' : 'cool', 'staticMenu' : true }
};
}
function getReportObj(){
return {
'data' : [
{ 'title' : 'Get report', 'placeholder': true, 'value' : '' },
{ 'title' : 'Campaign report', 'value' : 'report' },
{ 'title' : 'Scheduled report', 'value' : 'sched' },
],
'options' : {
'dropdownClass' : 'tidySmall cool',
'menuItemClass' : 'cool', 'carrotClass' : 'cool',
'staticMenu' : true
}
};
}
function getStatsObj(){
return {
'data' : [
{ 'title' : 'Lifetime', 'value' : '-1' },
{ 'title' : 'Today', 'value' : 'today' },
{ 'title' : 'Yesterday', 'value' : 'yesterday' },
{ 'title' : 'Week', 'value' : '7' },
{ 'title' : 'Month', 'value' : '30' }
],
'options' : {
'dropdownClass' : 'tidySmall royal',
'menuItemClass' : 'royal', 'carrotClass' : 'royal'
}
};
}
function getCampaigns(list, drafts){
var a = [],
cnt = 0;
loop(drafts, d);
loop(list, p);
return a;
function p(k, v){ a.push(new Campaign(v, v.id, cnt++)); }
function d(k, v){ a.push(new Campaign(v, v.id, cnt++, true)); }
}
function getCampaignRows(tbl){
var a = [];
loop(tbl.getSelectedRows(), p);
return a;
function p(k,v){ if(!v.getData().isDraft) a.push(v); }
}
function getDataObjValue(d, k, r){ if(r === undefined) r = null; if(isDefined(d) && isDefined(d[k])) return d[k]; else return r; }
function getIDArray(rows){ var a = []; for(var i=0, l=rows.length; i