diff --git a/.gitattributes b/.gitattributes index 3935aec7..9cdb2f68 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12,3 +12,4 @@ static/js/moment.min.js linguist-vendored static/js/jquery* linguist-vendored static/js/ui-bootstrap-* linguist-vendored static/js/datatables* linguist-vendored +static/js/sweetalert2.min.js linguist-vendored diff --git a/controllers/api.go b/controllers/api.go index e541abfd..dabb5d8b 100644 --- a/controllers/api.go +++ b/controllers/api.go @@ -128,6 +128,22 @@ func API_Campaigns_Id_Results(w http.ResponseWriter, r *http.Request) { } } +// API_Campaigns_Id_Complete effectively "ends" a campaign. +// Future phishing emails clicked will return a simple "404" page. +func API_Campaigns_Id_Complete(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id, _ := strconv.ParseInt(vars["id"], 0, 64) + switch { + case r.Method == "GET": + err := models.CompleteCampaign(id, ctx.Get(r, "user_id").(int64)) + if err != nil { + JSONResponse(w, models.Response{Success: false, Message: "Error completing campaign"}, http.StatusInternalServerError) + return + } + JSONResponse(w, models.Response{Success: true, Message: "Campaign completed successfully!"}, http.StatusOK) + } +} + // API_Groups returns a list of groups if requested via GET. // If requested via POST, API_Groups creates a new group and returns a reference to it. func API_Groups(w http.ResponseWriter, r *http.Request) { diff --git a/controllers/route.go b/controllers/route.go index 3f5e0267..44accc9f 100644 --- a/controllers/route.go +++ b/controllers/route.go @@ -47,6 +47,7 @@ func CreateAdminRouter() http.Handler { api.HandleFunc("/campaigns/", Use(API_Campaigns, mid.RequireAPIKey)) api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey)) api.HandleFunc("/campaigns/{id:[0-9]+}/results", Use(API_Campaigns_Id_Results, mid.RequireAPIKey)) + api.HandleFunc("/campaigns/{id:[0-9]+}/complete", Use(API_Campaigns_Id_Complete, mid.RequireAPIKey)) api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey)) api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey)) api.HandleFunc("/templates/", Use(API_Templates, mid.RequireAPIKey)) @@ -110,6 +111,11 @@ func PhishTracker(w http.ResponseWriter, r *http.Request) { if err != nil { Logger.Println(err) } + // Don't process events for completed campaigns + if c.Status == models.CAMPAIGN_COMPLETE { + http.NotFound(w, r) + return + } c.AddEvent(models.Event{Email: rs.Email, Message: models.EVENT_OPENED}) // Don't update the status if the user already clicked the link // or submitted data to the campaign @@ -157,11 +163,16 @@ func PhishHandler(w http.ResponseWriter, r *http.Request) { http.NotFound(w, r) return } - rs.UpdateStatus(models.STATUS_SUCCESS) c, err := models.GetCampaign(rs.CampaignId, rs.UserId) if err != nil { Logger.Println(err) } + // Don't process events for completed campaigns + if c.Status == models.CAMPAIGN_COMPLETE { + http.NotFound(w, r) + return + } + rs.UpdateStatus(models.STATUS_SUCCESS) p, err := models.GetPage(c.PageId, c.UserId) if err != nil { Logger.Println(err) diff --git a/models/campaign.go b/models/campaign.go index ec91c3ef..460fd37d 100644 --- a/models/campaign.go +++ b/models/campaign.go @@ -338,8 +338,29 @@ func DeleteCampaign(id int64) error { // Delete the campaign err = db.Delete(&Campaign{Id: id}).Error if err != nil { - Logger.Panicln(err) - return err + Logger.Println(err) + } + return err +} + +// CompleteCampaign effectively "ends" a campaign. +// Any future emails clicked will return a simple "404" page. +func CompleteCampaign(id int64, uid int64) error { + Logger.Printf("Marking campaign %d as complete\n", id) + c, err := GetCampaign(id, uid) + if err != nil { + return err + } + // Don't overwrite original completed time + if c.Status == CAMPAIGN_COMPLETE { + return nil + } + // Mark the campaign as complete + c.CompletedDate = time.Now() + c.Status = CAMPAIGN_COMPLETE + err = db.Where("id=? and user_id=?", id, uid).Save(&c).Error + if err != nil { + Logger.Println(err) } return err } diff --git a/static/css/main.css b/static/css/main.css index f14866d8..b8198b55 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -513,7 +513,14 @@ td.details-control{ margin-left:10px !important; } } - table.dataTable{ width:100% !important; } +.btn-blue { + color:#fff; + background-color:#428bca; + border-color:#428bca; +} +.btn-blue:hover{ + background-color:#64a1d6; +} diff --git a/static/css/sweetalert2.min.css b/static/css/sweetalert2.min.css new file mode 100644 index 00000000..afa27ee0 --- /dev/null +++ b/static/css/sweetalert2.min.css @@ -0,0 +1 @@ +.swal2-modal,.swal2-overlay{position:fixed;display:none}.swal2-overlay{background-color:rgba(0,0,0,.4);left:0;right:0;top:0;bottom:0;z-index:1000}.swal2-modal{background-color:#fff;font-family:"Source Sans Pro", Helvetica, Arial, sans-serif,Helvetica,Arial,sans-serif;border-radius:5px;box-sizing:border-box;text-align:center;left:50%;top:50%;margin-top:-200px;max-height:90%;overflow-x:hidden;overflow-y:auto;z-index:2000}.swal2-modal:focus{outline:0}.swal2-modal.loading{overflow-y:hidden}.swal2-modal h2{color:#575757;font-size:30px;text-align:center;font-weight:600;text-transform:none;position:relative;margin:0;padding:0;line-height:60px;display:block}.swal2-modal hr{height:10px;color:transparent;border:0}.swal2-modal button.styled{color:#fff;border:0;box-shadow:none;font-size:17px;font-weight:500;border-radius:5px;padding:10px 32px;margin:0 5px;cursor:pointer}.swal2-content,.swal2-icon{padding:0;position:relative}.swal2-modal button.styled:focus{outline:0}.swal2-modal button.styled:not(.loading)[disabled]{opacity:.4;cursor:no-drop}.swal2-modal button.styled.loading{box-sizing:border-box;border:4px solid transparent;width:40px;height:40px;padding:0;margin:-2px 30px;vertical-align:top;background-color:transparent!important;color:transparent;cursor:default;border-radius:100%;-webkit-animation:rotate-loading 1.5s linear 0s infinite normal;animation:rotate-loading 1.5s linear 0s infinite normal}.swal2-modal button.styled::-moz-focus-inner{border:0}.swal2-modal button:not(.styled).loading:after{display:inline-block;content:"";margin-left:5px;vertical-align:-1px;height:6px;width:6px;border:3px solid #999;border-right-color:transparent;border-radius:50%;-webkit-animation:rotate-loading 1.5s linear 0s infinite normal;animation:rotate-loading 1.5s linear 0s infinite normal}.swal2-checkbox input,.swal2-checkbox span,.swal2-radio input,.swal2-radio span{vertical-align:middle}.swal2-modal .swal2-image{margin:20px auto;max-width:100%}.swal2-modal .swal2-close{font-size:36px;line-height:36px;font-family:serif;position:absolute;top:5px;right:13px;cursor:pointer;color:#cfcfcf;-webkit-transition:all .1s ease;transition:all .1s ease}.swal2-modal .swal2-close:hover{color:#d55}.swal2-modal>.swal2-checkbox,.swal2-modal>.swal2-input,.swal2-modal>.swal2-radio,.swal2-modal>.swal2-select,.swal2-modal>.swal2-textarea{display:none}.swal2-content{font-size:18px;text-align:center;font-weight:400;float:none;margin:0;line-height:normal;color:#555}.swal2-icon.swal2-info,.swal2-icon.swal2-question,.swal2-icon.swal2-warning{font-size:60px;line-height:80px;text-align:center}.swal2-icon{width:80px;height:80px;border:4px solid grey;border-radius:50%;margin:20px auto 30px;box-sizing:content-box;cursor:default;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.swal2-icon.swal2-error{border-color:#f27474}.swal2-icon.swal2-error .x-mark{position:relative;display:block}.swal2-icon.swal2-error .line{position:absolute;height:5px;width:47px;background-color:#f27474;display:block;top:37px;border-radius:2px}.swal2-icon.swal2-error .line.left{-webkit-transform:rotate(45deg);transform:rotate(45deg);left:17px}.swal2-icon.swal2-error .line.right{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);right:16px}.swal2-icon.swal2-warning{font-family:"Source Sans Pro", Helvetica, Arial, sans-serif,Helvetica,Arial,sans-serif;color:#f8bb86;border-color:#f8bb86}.swal2-icon.swal2-info{font-family:"Open Sans",sans-serif;color:#3fc3ee;border-color:#3fc3ee}.swal2-icon.swal2-question{font-family:"Source Sans Pro", Helvetica, Arial, sans-serif,Helvetica,Arial,sans-serif;color:#c9dae1;border-color:#c9dae1}.swal2-icon.swal2-success{border-color:#a5dc86}.swal2-icon.swal2-success::after,.swal2-icon.swal2-success::before{content:'';position:absolute;width:60px;height:120px;background:#fff}.swal2-icon.swal2-success::before{border-radius:120px 0 0 120px;top:-7px;left:-33px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:60px 60px;transform-origin:60px 60px}.swal2-icon.swal2-success::after{border-radius:0 120px 120px 0;top:-11px;left:30px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:0 60px;transform-origin:0 60px}.swal2-icon.swal2-success .placeholder{width:80px;height:80px;border:4px solid rgba(165,220,134,.2);border-radius:50%;box-sizing:content-box;position:absolute;left:-4px;top:-4px;z-index:2}.swal2-icon.swal2-success .fix{width:7px;height:90px;background-color:#fff;position:absolute;left:28px;top:8px;z-index:1;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal2-icon.swal2-success .line{height:5px;background-color:#a5dc86;display:block;border-radius:2px;position:absolute;z-index:2}.swal2-icon.swal2-success .line.tip{width:25px;left:14px;top:46px;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swal2-icon.swal2-success .line.long{width:47px;right:8px;top:38px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal2-checkbox,.swal2-input,.swal2-radio,.swal2-select,.swal2-textarea{margin:20px auto}.swal2-input:not([type=file]),.swal2-textarea{width:100%;box-sizing:border-box;border-radius:3px;border:1px solid #d7d7d7;font-size:18px;box-shadow:inset 0 1px 1px rgba(0,0,0,.06);-webkit-transition:all .3s;transition:all .3s}.swal2-input:not([type=file]).error,.swal2-textarea.error{border-color:#f06e57!important}.swal2-input:not([type=file]):focus,.swal2-textarea:focus{outline:0;box-shadow:0 0 3px #c4e6f5;border:1px solid #b4dbed}.swal2-input:not([type=file]):focus::-moz-placeholder,.swal2-textarea:focus::-moz-placeholder{-webkit-transition:opacity .3s 30ms ease;transition:opacity .3s 30ms ease;opacity:.8}.swal2-input:not([type=file]):focus:-ms-input-placeholder,.swal2-textarea:focus:-ms-input-placeholder{-webkit-transition:opacity .3s 30ms ease;transition:opacity .3s 30ms ease;opacity:.8}.swal2-input:not([type=file]):focus::-webkit-input-placeholder,.swal2-textarea:focus::-webkit-input-placeholder{-webkit-transition:opacity .3s 30ms ease;transition:opacity .3s 30ms ease;opacity:.8}.swal2-input:not([type=file])::-moz-placeholder,.swal2-textarea::-moz-placeholder{color:#bdbdbd}.swal2-input:not([type=file]):-ms-input-placeholder,.swal2-textarea:-ms-input-placeholder{color:#bdbdbd}.swal2-input:not([type=file])::-webkit-input-placeholder,.swal2-textarea::-webkit-input-placeholder{color:#bdbdbd}.swal2-input:not([type=file]){height:43px;padding:0 12px}.swal2-input[type=file]{font-size:20px}.swal2-textarea{height:108px;padding:12px}.swal2-select{color:#555;font-size:inherit;padding:5px 10px;min-width:40%;max-width:100%}.swal2-radio{border:0}.swal2-radio label:not(:first-child){margin-left:20px}.swal2-radio input{margin:0 3px 0 0}.swal2-checkbox{color:#555}.swal2-validationerror{background-color:#f1f1f1;margin:0 -20px;overflow:hidden;padding:10px;color:#797979;font-size:16px;font-weight:400;display:none}.swal2-validationerror::before{content:"!";display:inline-block;width:24px;height:24px;border-radius:50%;background-color:#ea7d7d;color:#fff;line-height:24px;text-align:center;margin-right:10px}@-webkit-keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes showSweetAlert{0%{-webkit-transform:scale(.7);transform:scale(.7)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}100%{-webkit-transform:scale(.5);transform:scale(.5);opacity:0}}@keyframes hideSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}100%{-webkit-transform:scale(.5);transform:scale(.5);opacity:0}}.show-swal2{-webkit-animation:showSweetAlert .3s;animation:showSweetAlert .3s}.show-swal2.no-animation{-webkit-animation:none;animation:none}.hide-swal2{-webkit-animation:hideSweetAlert .15s;animation:hideSweetAlert .15s}.hide-swal2.no-animation{-webkit-animation:none;animation:none}@-webkit-keyframes animate-success-tip{0%,54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@keyframes animate-success-tip{0%,54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@-webkit-keyframes animate-success-long{0%,65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@keyframes animate-success-long{0%,65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@-webkit-keyframes rotatePlaceholder{0%,5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}100%,12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}@keyframes rotatePlaceholder{0%,5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}100%,12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}.animate-success-tip{-webkit-animation:animate-success-tip .75s;animation:animate-success-tip .75s}.animate-success-long{-webkit-animation:animate-success-long .75s;animation:animate-success-long .75s}.swal2-icon.swal2-success.animate::after{-webkit-animation:rotatePlaceholder 4.25s ease-in;animation:rotatePlaceholder 4.25s ease-in}@-webkit-keyframes animate-error-icon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}100%{-webkit-transform:rotateX(0);transform:rotateX(0);opacity:1}}@keyframes animate-error-icon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}100%{-webkit-transform:rotateX(0);transform:rotateX(0);opacity:1}}.animate-error-icon{-webkit-animation:animate-error-icon .5s;animation:animate-error-icon .5s}@-webkit-keyframes animate-x-mark{0%,50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}100%{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}@keyframes animate-x-mark{0%,50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}100%{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}.animate-x-mark{-webkit-animation:animate-x-mark .5s;animation:animate-x-mark .5s}@-webkit-keyframes pulse-warning{0%{border-color:#f8d486}100%{border-color:#f8bb86}}@keyframes pulse-warning{0%{border-color:#f8d486}100%{border-color:#f8bb86}}.pulse-warning{-webkit-animation:pulse-warning .75s infinite alternate;animation:pulse-warning .75s infinite alternate}@-webkit-keyframes rotate-loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate-loading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}} diff --git a/static/js/app/campaign_results.js b/static/js/app/campaign_results.js index fc0a48d0..b1b3f258 100644 --- a/static/js/app/campaign_results.js +++ b/static/js/app/campaign_results.js @@ -1,4 +1,5 @@ var map = null +var doPoll = true; // statuses is a helper map to point result statuses to ui classes var statuses = { @@ -94,6 +95,52 @@ function deleteCampaign() { } } +// Completes a campaign after prompting the user +function completeCampaign() { + swal({ + title: "Are you sure?", + text: "Gophish will stop processing events for this campaign", + type: "warning", + animation: false, + showCancelButton: true, + confirmButtonText: "Complete Campaign", + confirmButtonColor: "#428bca", + reverseButtons: true, + allowOutsideClick: false, + preConfirm: function() { + return new Promise(function(resolve, reject) { + api.campaignId.complete(campaign.id) + .success(function(msg) { + resolve() + }) + .error(function(data) { + reject(data.responseJSON.message) + }) + }) + } + }).then(function() { + swal( + 'Campaign Completed!', + 'This campaign has been completed!', + 'success' + ); + $('#complete_button')[0].disabled = true; + $('#complete_button').text('Completed!') + doPoll = false; + }) + /* + if (confirm("Are you sure you want to delete: " + campaign.name + "?")) { + api.campaignId.delete(campaign.id) + .success(function(msg) { + location.href = '/campaigns' + }) + .error(function(e) { + $("#modal\\.flashes").empty().append("
\ + " + data.responseJSON.message + "
") + }) + }*/ +} + // Exports campaign results as a CSV file function exportAsCSV(scope) { exportHTML = $("#exportButton").html() @@ -298,7 +345,12 @@ function load() { $("#campaignResults").show() // Set the title $("#page-title").text("Results for " + c.name) - // Setup tooltips + if (c.status == "Completed") { + $('#complete_button')[0].disabled = true; + $('#complete_button').text('Completed!'); + doPoll = false; + } + // Setup tooltips $('[data-toggle="tooltip"]').tooltip() // Setup viewing the details of a result $("#resultsTable").on("click", ".timeline-event-details", function() { @@ -554,11 +606,13 @@ function load() { errorFlash(" Campaign not found!") }) } - $(document).ready(function() { load(); // Start the polling loop function refresh() { + if (!doPoll) { + return; + } $("#refresh_message").show() poll() $("#refresh_message").hide() diff --git a/static/js/gophish.js b/static/js/gophish.js index 7f6e5474..21cfc2a3 100644 --- a/static/js/gophish.js +++ b/static/js/gophish.js @@ -62,6 +62,10 @@ var api = { // results() - Queries the API for GET /campaigns/:id/results results: function(id) { return query("/campaigns/" + id + "/results", "GET", {}, true) + }, + // complete() - Completes a campaign at POST /campaigns/:id/complete + complete: function(id) { + return query("/campaigns/" + id + "/complete", "GET", {}, true) } }, // groups contains the endpoints for /groups diff --git a/static/js/sweetalert2.min.js b/static/js/sweetalert2.min.js new file mode 100644 index 00000000..e1b32dd1 --- /dev/null +++ b/static/js/sweetalert2.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Sweetalert2=t()}(this,function(){"use strict";function e(){if(void 0===arguments[0])return console.error("sweetAlert2 expects at least 1 attribute!"),!1;var e=c({},N);switch(typeof arguments[0]){case"string":e.title=arguments[0],e.text=arguments[1]||"",e.type=arguments[2]||"";break;case"object":c(e,arguments[0]),e.extraParams=arguments[0].extraParams,"email"===e.input&&null===e.inputValidator&&(e.inputValidator=function(e){return new Promise(function(t,n){var o=/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;o.test(e)?t():n("Invalid email address")})});break;default:return console.error('Unexpected type of argument! Expected "string" or "object", got '+typeof arguments[0]),!1}V(e);var o=f();return new Promise(function(r,a){function l(e,t){for(var n=0;n0;)N.removeAttribute(N.attributes[0].name);for(var j in e.inputAttributes)N.setAttribute(j,e.inputAttributes[j]);N.className=I,e.inputClass&&g(N,e.inputClass),E(N)}var K;switch(e.input){case"text":case"email":case"password":case"file":N=C(o,i.input),N.value=e.inputValue,N.placeholder=e.inputPlaceholder,N.type=e.input,k(N);break;case"select":var W=C(o,i.select);if(W.innerHTML="",e.inputPlaceholder){var U=document.createElement("option");U.innerHTML=e.inputPlaceholder,U.value="",U.disabled=!0,U.selected=!0,W.appendChild(U)}K=function(t){for(var n in t){var o=document.createElement("option");o.value=n,o.innerHTML=t[n],e.inputValue===n&&(o.selected=!0),W.appendChild(o)}k(W),W.focus()};break;case"radio":var z=C(o,i.radio);z.innerHTML="",K=function(t){for(var n in t){var o=1,r=document.createElement("input"),a=document.createElement("label"),l=document.createElement("span");r.type="radio",r.name=i.radio,r.value=n,r.id=i.radio+"-"+o++,e.inputValue===n&&(r.checked=!0),l.innerHTML=t[n],a.appendChild(r),a.appendChild(l),a["for"]=r.id,z.appendChild(a)}k(z);var c=z.querySelectorAll("input");c.length&&c[0].focus()};break;case"checkbox":var R=C(o,i.checkbox),Z=o.querySelector("#"+i.checkbox);Z.value=1,Z.checked=Boolean(e.inputValue);var $=R.getElementsByTagName("span");$.length&&R.removeChild($[0]),$=document.createElement("span"),$.innerHTML=e.inputPlaceholder,R.appendChild($),k(R);break;case"textarea":var _=C(o,i.textarea);_.value=e.inputValue,_.placeholder=e.inputPlaceholder,k(_);break;case null:break;default:console.error('Unexpected type of input! Expected "text" or "email" or "password", "select", "checkbox", "textarea" or "file", got '+typeof arguments[0])}"select"!==e.input&&"radio"!==e.input||(e.inputOptions instanceof Promise?(t.showLoading(),e.inputOptions.then(function(e){t.hideLoading(),K(e)})):"object"==typeof e.inputOptions?K(e.inputOptions):console.error("Unexpected type of inputOptions! Expected object or Promise, got "+e.inputOptions)),D(),H(e.animation,e.onOpen),l(-1,1)})}function t(){var n=arguments,o=f();return null===o&&(t.init(),o=f()),h(o,"visible")&&O(),e.apply(this,n)}var n="swal2-",o=function(e){var t={};for(var o in e)t[e[o]]=n+e[o];return t},i=o(["container","modal","overlay","close","content","spacer","confirm","cancel","icon","image","input","select","radio","checkbox","textarea","validationerror"]),r=o(["success","warning","info","question","error"]),a={title:"",text:"",html:"",type:null,animation:!0,allowOutsideClick:!0,allowEscapeKey:!0,showConfirmButton:!0,showCancelButton:!1,preConfirm:null,confirmButtonText:"OK",confirmButtonColor:"#3085d6",confirmButtonClass:null,cancelButtonText:"Cancel",cancelButtonColor:"#aaa",cancelButtonClass:null,buttonsStyling:!0,reverseButtons:!1,showCloseButton:!1,showLoaderOnConfirm:!1,imageUrl:null,imageWidth:null,imageHeight:null,imageClass:null,timer:null,width:500,padding:20,background:"#fff",input:null,inputPlaceholder:"",inputValue:"",inputOptions:{},inputAutoTrim:!0,inputClass:null,inputAttributes:{},inputValidator:null,onOpen:null,onClose:null},l='
',c=function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e},s=function(e,t){e=String(e).replace(/[^0-9a-f]/gi,""),e.length<6&&(e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]),t=t||0;for(var n="#",o=0;3>o;o++){var i=parseInt(e.substr(2*o,2),16);i=Math.round(Math.min(Math.max(0,i+i*t),255)).toString(16),n+=("00"+i).substr(i.length)}return n},u=n+"mediaquery",d={previousDocumentClick:null,previousWindowKeyDown:null,previousActiveElement:null},p=function(e){return document.querySelector("."+e)},f=function(){return p(i.modal)},m=function(){return p(i.overlay)},v=function(){return p(i.confirm)},y=function(){return p(i.cancel)},h=function(e,t){return new RegExp(" "+t+" ").test(" "+e.className+" ")},b=function(e){e.focus();var t=e.value;e.value="",e.value=t},g=function(e,t){t&&!h(e,t)&&(e.className+=" "+t)},w=function(e,t){var n=" "+e.className.replace(/[\t\r\n]/g," ")+" ";if(h(e,t)){for(;n.indexOf(" "+t+" ")>=0;)n=n.replace(" "+t+" "," ");e.className=n.replace(/^\s+|\s+$/g,"")}},C=function(e,t){for(var n=0;n1?1:i,n=+new Date,+e.style.opacity<1&&setTimeout(o,t)};o()}},A=function(e,t){if(+e.style.opacity>0){t=t||16;var n=e.style.opacity,o=+new Date,i=function(){var r=new Date-o,a=+e.style.opacity-r/(100*n);e.style.opacity=a,o=+new Date,+e.style.opacity>0?setTimeout(i,t):E(e)};i()}},M=function(e){if("function"==typeof MouseEvent){var t=new MouseEvent("click",{view:window,bubbles:!1,cancelable:!0});e.dispatchEvent(t)}else if(document.createEvent){var n=document.createEvent("MouseEvents");n.initEvent("click",!1,!1),e.dispatchEvent(n)}else document.createEventObject?e.fireEvent("onclick"):"function"==typeof e.onclick&&e.onclick()},T=function(e){"function"==typeof e.stopPropagation?(e.stopPropagation(),e.preventDefault()):window.event&&window.event.hasOwnProperty("cancelBubble")&&(window.event.cancelBubble=!0)},P=function(){var e=document.createElement("div"),t={WebkitAnimation:"webkitAnimationEnd",MozAnimation:"animationend",OAnimation:"oAnimationEnd oanimationend",msAnimation:"MSAnimationEnd",animation:"animationend"};for(var n in t)if(t.hasOwnProperty(n)&&void 0!==e.style[n])return t[n];return!1}(),O=function(){var e=f();window.onkeydown=d.previousWindowKeyDown,document.onclick=d.previousDocumentClick,d.previousActiveElement&&d.previousActiveElement.focus(),clearTimeout(e.timeout);var t=document.getElementsByTagName("head")[0],n=document.getElementById(u);n&&t.removeChild(n)},N=c({},a),V=function(e){var t,n=f();n.style.width=e.width+"px",n.style.padding=e.padding+"px",n.style.marginLeft=-e.width/2+"px",n.style.background=e.background;var o=document.getElementsByTagName("head")[0],a=document.createElement("style");a.type="text/css",a.id=u;var l=5,c=e.width+parseInt(e.width*(l/100)*2,10);a.innerHTML="@media screen and (max-width: "+c+"px) {."+i.modal+" {width: auto !important;left: "+l+"% !important;right: "+l+"% !important;margin-left: 0 !important;}}",o.appendChild(a);var s=n.querySelector("h2"),d=n.querySelector("."+i.content),p=v(),m=y(),h=n.querySelector("."+i.spacer),b=n.querySelector("."+i.close);if(s.innerHTML=e.title.split("\n").join("
"),e.text||e.html){if("object"==typeof e.html)if(d.innerHTML="",0 in e.html)for(t=0;t in e.html;t++)d.appendChild(e.html[t]);else d.appendChild(e.html);else d.innerHTML=e.html||e.text.split("\n").join("
");x(d)}else S(d);if(e.showCloseButton?x(b):S(b),n.className=i.modal,e.customClass&&g(n,e.customClass),S(n.querySelectorAll("."+i.icon)),e.type){var C=!1;for(var k in r)if(e.type===k){C=!0;break}if(!C)return console.error("Unknown alert type: "+e.type),!1;var E=n.querySelector("."+i.icon+"."+r[e.type]);switch(x(E),e.type){case"success":g(E,"animate"),g(E.querySelector(".tip"),"animate-success-tip"),g(E.querySelector(".long"),"animate-success-long");break;case"error":g(E,"animate-error-icon"),g(E.querySelector(".x-mark"),"animate-x-mark");break;case"warning":g(E,"pulse-warning")}}var L=n.querySelector("."+i.image);e.imageUrl?(L.setAttribute("src",e.imageUrl),x(L),e.imageWidth&&L.setAttribute("width",e.imageWidth),e.imageHeight&&L.setAttribute("height",e.imageHeight),e.imageClass&&g(L,e.imageClass)):S(L),e.showCancelButton?m.style.display="inline-block":S(m),e.showConfirmButton?B(p,"display"):S(p),e.showConfirmButton||e.showCancelButton?x(h):S(h),p.innerHTML=e.confirmButtonText,m.innerHTML=e.cancelButtonText,e.buttonsStyling&&(p.style.backgroundColor=e.confirmButtonColor,m.style.backgroundColor=e.cancelButtonColor),p.className=i.confirm,g(p,e.confirmButtonClass),m.className=i.cancel,g(m,e.cancelButtonClass),e.buttonsStyling?(g(p,"styled"),g(m,"styled")):(w(p,"styled"),w(m,"styled"),p.style.backgroundColor=p.style.borderLeftColor=p.style.borderRightColor="",m.style.backgroundColor=m.style.borderLeftColor=m.style.borderRightColor=""),e.animation===!0?w(n,"no-animation"):g(n,"no-animation")},H=function(e,t){var n=f();e?(q(m(),10),g(n,"show-swal2"),w(n,"hide-swal2")):x(m()),x(n),d.previousActiveElement=document.activeElement,g(n,"visible"),null!==t&&"function"==typeof t&&t.call(this,n)},D=function(){var e=f();e.style.marginTop=L(e)};return t.queue=function(e){return new Promise(function(n,o){!function i(r,a){r + + {{end}} diff --git a/templates/campaigns.html b/templates/campaigns.html index c1f7df31..b289707e 100644 --- a/templates/campaigns.html +++ b/templates/campaigns.html @@ -49,10 +49,10 @@ - - - - + + + +