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 = '
Create CampaignManage Domain Lists
', 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