// Save campaign app // =============================================== // Takes in data obj, an element to append to, and utility functions // // Uses Campaign's dataset // var saveCampaign = (function(){ 'use strict' var errServerError = 'Oops, server error, please try to save again in few seconds.'; var prospectingMsg = 'Having at-least 1 of the filters in advanced campaign settings will greatly increase the performance of this campaign. Are you sure you want to continue without filters?', budgetValChgMsg = 'Hey there! We noticed the budget has changed. When you save this campaign, your account will be charged for the difference between the new and old budgets. Is this ok?', budgetTypeChgMsg = 'Hey there! We noticed your budget type has changed. When you save this campaign, your account may be charged for the difference between the new and old budgets. Is this ok?', schedulingChgMsg = 'Hey there! We noticed your scheduling has changed from an inactive to active state. When you save this campaign, your account may be charged for the difference between current funds and what the flight budget. Is this ok?', billConfirmationMsg = 'Hey there! When you save this campaign, your account will be charged for the amount set in your budget. Is this ok?', budgetChangeTitle = 'Warning, your budget and/or schedule has changed.'; return newSave; function newSave(d, uid, tmplCmp, cid, did, fns){ return new Save(d, uid, tmplCmp, cid, did, fns); } function Save(d, uid, tmplCmp, cid, did, fns){ var invalid = getInvalidItems(d), ep = 'campaigns'; if(invalid === null){ prospectingCheck(); } else { fns.setMissingFields(invalid); } function focusCheck(){ if(!cid || cid.length === 0 || !!tmplCmp) { if(!d.ioState){ billingCheck() return } } else if(d.originalBudget !== d.budget){ budgetChangeConfirmation(); return } if(!!cid){ edit(true); } else { save(); } } function save(){ sanitizeData(); apiRequest('POST', ep + "/byAdv", uid, d, !did ? redirect : delDraft); } function edit(ok){ if(!ok) return sanitizeData(); apiRequest('PUT', ep + "/byCID", d.id, d, redirect); } function sanitizeData(){ d = d.clean(d); } function prospectingCheck(){ if(hasApps(d)) { return focusCheck(); } prospectingConfirmation(); } function prospectingConfirmation(){ new AlertModal({ 'title' : 'Alert!', 'message' : prospectingMsg, 'actionOne' : 'Let me fix that!', 'actionTwo' : 'I understand' }, prospectingConfirmationCB); } function prospectingConfirmationCB(e){ if(e) setTimeout(focusCheck, 1); } function budgetChangeConfirmation(){ if (d.budget != d.originalBudget) { // var budget = 0; // if(d.budget > d.originalBudget) budget = (d.budget - d.originalBudget); new AlertModal({ 'title' : budgetChangeTitle, 'message' : budgetValChgMsg, 'actionOne' : 'Oh, nevermind', 'actionTwo' : 'Confirm Changes', 'actionTwoClass' : 'mint' }, edit); } else if (d.budgetType != d.originalBudgetType){ new AlertModal({ 'title' : 'Just to confirm!', 'message' : budgetTypeChgMsg, 'actionOne' : 'Oh, nevermind', 'actionTwo' : 'Confirm Changes', 'actionTwoClass' : 'mint' }, edit); } else if (d.budgetType == "flight" && hasSchedulingChanged(d)) { var tdy = new CalendarAssistant().getCurrentDay(), sd = d.startDate, osd = d.originalStartDate, ed = d.endDate, oed = d.originalEndDate, altState = isStartNowActive(sd, osd, tdy) || isEndNowActive(ed, oed, tdy); if(altState && isDateEarlier(sd, tdy) && isDateEarlier(tdy, ed)){ new AlertModal({ 'title' : 'Just to confirm!', 'message' : schedulingChgMsg, 'actionOne' : 'Oh, nevermind', 'actionTwo' : 'Confirm Changes', 'actionTwoClass' : 'mint' }, edit); } else edit(true); } else { edit(true); } } function billingCheck(){ if(isDefined(d.billing) && (d.billing.isIO || isDefined(d.billing.cc))){ billConfirmation(); return } else { // Get rid of this setBilling(); } } function setBilling(){ var modal = new Modal({ 'title' : 'Please add your billing info to continue:', 'className' : 'editBilling doubleColumnForm' }); NewEditBilling(uid, fns.notif, modal.element.querySelector(".inner"), null, function(){ modal.close(); refreshBilling(); }); } function refreshBilling(){ apiRequest("GET", "billing", uid, null, function(body){ if(!body){ fns.setError("Error loading") return } d.billing = body; }); } function billConfirmation(){ new AlertModal({ 'title' : 'Just to confirm!', 'message' : billConfirmationMsg, 'actionOne' : 'Oh, nevermind', 'actionTwo' : 'Yes, let\'s do this!' }, billConfirmationCB); } function billConfirmationCB(e){ if(e) save(); } function delDraft(e, s){ if(s !== 200){ fns.setErrors(getErrorMsg(e, errServerError)); return; } new HttpRequest('DELETE', '/api/v1/campaignDraft/' + did, null, null, 'json', redirect); } function redirect(e, s){ if(s === 200) pop('Pop!', 'Dashboard - Campaigns', '/dashboard/campaigns'); else fns.setErrors(getErrorMsg(e, errServerError)); } } function hasDateChanged(a, b){ return a.display != b.display; } function hasStartDateChanged(d){ return d.startDate.display != d.originalStartDate.display; } function hasEndDateChanged(d){ return d.endDate.display != d.originalEndDate.display; } function hasSchedulingChanged(d){ return hasStartDateChanged(d) || hasEndDateChanged(d); } function isStartNowActive(a, b, tdy){ return hasDateChanged(a, b) && isDateEarlier(a, tdy) && !isDateEarlier(b, tdy); } function isEndNowActive(a, b, tdy){ return hasDateChanged(a, b) && isDateEarlier(tdy, a) && !isDateEarlier(tdy, b); } function isDateEarlier(a, b){ if(a.year < b.year) return true; else if(a.year > b.year) return false; if(a.monthValue < b.monthValue) return true; else if(a.monthValue > b.monthValue) return false; if(a.date < b.date) return true; } function isValidSchedule(o){ if(!o.scheduled){ return true; } if(o.start === 0 || o.end === 0 || isNaN(o.start) || isNaN(o.end)){ return false; } if(o.end <= o.start){ return false } return true } function isValidGeo(o){ if(o && o.targeting !== 'Specific Location') o.cities = o.zipCodes = o.states = o.dmas = null; if(!o || o.targeting === 'All USA' || o.targeting == 'All Canada' || locC(o)){ return true; } return false; function locC(o){ return o.targeting === 'Specific Location' && (itemC(o.cities) || itemC(o.zipCodes) || itemC(o.states) || itemC(o.dmas) ); } function itemC(item){ return !!item && item.length > 0; } } function hasApps(d){ var m = false; loop(d.apps, p); return m; function p(k, v){ if(k !== 'pacing' && v.status === true){ m = true; return true; } } } function getInvalidItems(o){ var budget = (function() { switch(o.budgetType) { case 'daily': return o.budget * 7; case 'monthly': return o.budget / 4; } return o.budget; })(), a = []; if (!budget && !o.impBudget) { a.push('Missing budget'); } else if(budget < 5 && o.impBudget < 100) { a.push('Budget does not meet minimum requirement'); } if(!isDefined(o.name) || o.name === '') a.push('Missing campaign name'); if(!isValidSchedule(o)) a.push('Invalid scheduling, please check your selected dates'); if(!hasApps(o) && (!isDefined(o.segments) || o.segments.length === 0) && getEvegments(o).length === 0) a.push('Please select at least one segment or an app.'); if(!isDefined(o.adGroups) || o.adGroups.length === 0) a.push('Please select at least one ad group'); if(!isValidGeo(o.apps.geography)) a.push('If US Only is enabled, please ensure to select at least one city, DMA, or zip code.'); if(o.weatherStatus && !isValidWeather()) a.push('Weather is selected, but not all the required fields are set.'); if(o.budgetType === "flight" && o.unrestricted){ a.push("Flight based campaigns must have scheduling enabled and intended dates selected."); } return a.length > 0 ? a : null; } function getEvegments(o) { if(o.apps.evegment && o.apps.evegment.status) return o.apps.evegment.list; return []; } })();