|
|
@@ -43,6 +43,7 @@ |
|
|
var pendingPath = ""; |
|
|
var pendingPath = ""; |
|
|
var pendingCampaignReview = null; |
|
|
var pendingCampaignReview = null; |
|
|
var campaignTestAccepted = false; |
|
|
var campaignTestAccepted = false; |
|
|
|
|
|
var recipientSelection = {}; |
|
|
var dispatchSessionPid = 0; |
|
|
var dispatchSessionPid = 0; |
|
|
var dispatchSessionToken = ""; |
|
|
var dispatchSessionToken = ""; |
|
|
var dispatchSessionPath = ""; |
|
|
var dispatchSessionPath = ""; |
|
|
@@ -232,7 +233,7 @@ |
|
|
document.getElementById("importMessage").innerText = "Import failed: " + error.message; |
|
|
document.getElementById("importMessage").innerText = "Import failed: " + error.message; |
|
|
} finally { |
|
|
} finally { |
|
|
if (db !== null && db.State === 1) db.Close(); |
|
|
if (db !== null && db.State === 1) db.Close(); |
|
|
if (succeeded) refreshStatus(); |
|
|
|
|
|
|
|
|
if (succeeded) { refreshStatus(); refreshRecipients(); } |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
function addSuppression() { |
|
|
function addSuppression() { |
|
|
@@ -261,7 +262,7 @@ |
|
|
document.getElementById("suppressMessage").innerText = "Suppression failed: " + error.message; |
|
|
document.getElementById("suppressMessage").innerText = "Suppression failed: " + error.message; |
|
|
} finally { |
|
|
} finally { |
|
|
if (db !== null && db.State === 1) db.Close(); |
|
|
if (db !== null && db.State === 1) db.Close(); |
|
|
if (succeeded) refreshStatus(); |
|
|
|
|
|
|
|
|
if (succeeded) { refreshStatus(); refreshRecipients(); } |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
function powerShellHost() { |
|
|
function powerShellHost() { |
|
|
@@ -460,6 +461,87 @@ |
|
|
if (db !== null && db.State === 1) db.Close(); |
|
|
if (db !== null && db.State === 1) db.Close(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
function selectedRecipientIds() { |
|
|
|
|
|
var ids = []; |
|
|
|
|
|
for (var id in recipientSelection) { |
|
|
|
|
|
if (recipientSelection.hasOwnProperty(id) && recipientSelection[id]) ids.push(Number(id)); |
|
|
|
|
|
} |
|
|
|
|
|
return ids; |
|
|
|
|
|
} |
|
|
|
|
|
function updateRecipientCount() { |
|
|
|
|
|
var total = 0; |
|
|
|
|
|
for (var id in recipientSelection) if (recipientSelection.hasOwnProperty(id)) total++; |
|
|
|
|
|
document.getElementById("recipientCount").innerText = |
|
|
|
|
|
selectedRecipientIds().length + " of " + total + " eligible contacts selected"; |
|
|
|
|
|
} |
|
|
|
|
|
function toggleRecipient(box) { |
|
|
|
|
|
recipientSelection[box.value] = box.checked; |
|
|
|
|
|
updateRecipientCount(); |
|
|
|
|
|
invalidateCampaignReview(); |
|
|
|
|
|
} |
|
|
|
|
|
function setVisibleRecipients(checked) { |
|
|
|
|
|
var boxes = document.getElementById("recipientList").getElementsByTagName("input"); |
|
|
|
|
|
for (var i = 0; i < boxes.length; i++) { |
|
|
|
|
|
if (boxes[i].parentNode.parentNode.style.display === "none") continue; |
|
|
|
|
|
boxes[i].checked = checked; |
|
|
|
|
|
recipientSelection[boxes[i].value] = checked; |
|
|
|
|
|
} |
|
|
|
|
|
updateRecipientCount(); |
|
|
|
|
|
invalidateCampaignReview(); |
|
|
|
|
|
} |
|
|
|
|
|
function filterRecipients() { |
|
|
|
|
|
var needle = document.getElementById("recipientFilter").value.toLowerCase(); |
|
|
|
|
|
var rows = document.getElementById("recipientList").getElementsByTagName("tr"); |
|
|
|
|
|
for (var i = 0; i < rows.length; i++) { |
|
|
|
|
|
rows[i].style.display = |
|
|
|
|
|
rows[i].getAttribute("data-text").indexOf(needle) === -1 ? "none" : ""; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
function refreshRecipients() { |
|
|
|
|
|
var db = null; |
|
|
|
|
|
try { |
|
|
|
|
|
db = openDatabase().db; |
|
|
|
|
|
var rows = db.Execute("SELECT c.[Id],c.[EmailOriginal],c.[BusinessName] FROM [Contact] AS c " + |
|
|
|
|
|
"LEFT JOIN [Suppression] AS s ON c.[EmailKey]=s.[EmailKey] WHERE s.[EmailKey] IS NULL " + |
|
|
|
|
|
"AND c.[Country]='US' AND c.[EligibilityBasis]='public_listing' ORDER BY c.[Id]"); |
|
|
|
|
|
var body = document.getElementById("recipientList"); |
|
|
|
|
|
while (body.firstChild) body.removeChild(body.firstChild); |
|
|
|
|
|
var known = recipientSelection; |
|
|
|
|
|
recipientSelection = {}; |
|
|
|
|
|
while (!rows.EOF) { |
|
|
|
|
|
var id = String(rows.Fields("Id").Value); |
|
|
|
|
|
var email = String(rows.Fields("EmailOriginal").Value); |
|
|
|
|
|
var business = rows.Fields("BusinessName").Value; |
|
|
|
|
|
business = business === null ? "" : String(business); |
|
|
|
|
|
recipientSelection[id] = known.hasOwnProperty(id) ? known[id] : true; |
|
|
|
|
|
var tr = document.createElement("tr"); |
|
|
|
|
|
tr.setAttribute("data-text", (email + " " + business).toLowerCase()); |
|
|
|
|
|
var boxCell = document.createElement("td"); |
|
|
|
|
|
var box = document.createElement("input"); |
|
|
|
|
|
box.type = "checkbox"; |
|
|
|
|
|
box.value = id; |
|
|
|
|
|
box.checked = recipientSelection[id]; |
|
|
|
|
|
box.onclick = function () { toggleRecipient(this); }; |
|
|
|
|
|
boxCell.appendChild(box); |
|
|
|
|
|
var emailCell = document.createElement("td"); |
|
|
|
|
|
emailCell.innerText = email; |
|
|
|
|
|
var businessCell = document.createElement("td"); |
|
|
|
|
|
businessCell.innerText = business; |
|
|
|
|
|
tr.appendChild(boxCell); |
|
|
|
|
|
tr.appendChild(emailCell); |
|
|
|
|
|
tr.appendChild(businessCell); |
|
|
|
|
|
body.appendChild(tr); |
|
|
|
|
|
rows.MoveNext(); |
|
|
|
|
|
} |
|
|
|
|
|
rows.Close(); |
|
|
|
|
|
updateRecipientCount(); |
|
|
|
|
|
filterRecipients(); |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
document.getElementById("campaignMessage").innerText = "Recipient list failed: " + error.message; |
|
|
|
|
|
} finally { |
|
|
|
|
|
if (db !== null && db.State === 1) db.Close(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
function invalidateCampaignReview() { |
|
|
function invalidateCampaignReview() { |
|
|
pendingCampaignReview = null; |
|
|
pendingCampaignReview = null; |
|
|
campaignTestAccepted = false; |
|
|
campaignTestAccepted = false; |
|
|
@@ -475,6 +557,7 @@ |
|
|
Name: document.getElementById("campaignName").value, |
|
|
Name: document.getElementById("campaignName").value, |
|
|
Subject: document.getElementById("campaignSubject").value, |
|
|
Subject: document.getElementById("campaignSubject").value, |
|
|
TemplateId: document.getElementById("campaignTemplateVersion").value, |
|
|
TemplateId: document.getElementById("campaignTemplateVersion").value, |
|
|
|
|
|
ContactIds: selectedRecipientIds(), |
|
|
ReviewToken: pendingCampaignReview ? pendingCampaignReview.Token : "", |
|
|
ReviewToken: pendingCampaignReview ? pendingCampaignReview.Token : "", |
|
|
TestReceived: document.getElementById("confirmReceived").checked |
|
|
TestReceived: document.getElementById("confirmReceived").checked |
|
|
}; |
|
|
}; |
|
|
@@ -577,6 +660,7 @@ |
|
|
refreshStatus(); |
|
|
refreshStatus(); |
|
|
refreshTemplates(); |
|
|
refreshTemplates(); |
|
|
refreshCampaigns(); |
|
|
refreshCampaigns(); |
|
|
|
|
|
refreshRecipients(); |
|
|
initializeDispatch(); |
|
|
initializeDispatch(); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
document.getElementById("dispatchMessage").innerText = |
|
|
document.getElementById("dispatchMessage").innerText = |
|
|
@@ -866,10 +950,19 @@ |
|
|
</div> |
|
|
</div> |
|
|
<div class="panel tab-pane" data-tab="campaigns" role="tabpanel"> |
|
|
<div class="panel tab-pane" data-tab="campaigns" role="tabpanel"> |
|
|
<h2>Review and approve a campaign</h2> |
|
|
<h2>Review and approve a campaign</h2> |
|
|
<p>Approval captures currently eligible contacts and the selected template version. It requires a complete postal address in config.ini, a campaign-specific internal test, and your confirmation that you received it. Approved campaigns stay paused until you resume them.</p> |
|
|
|
|
|
|
|
|
<p>Approval captures the contacts you select below (from currently eligible, unsuppressed contacts) and the selected template version. It requires a complete postal address in config.ini, a campaign-specific internal test, and your confirmation that you received it. Approved campaigns stay paused until you resume them.</p> |
|
|
<label class="field">Campaign name <input id="campaignName" type="text" maxlength="200" oninput="invalidateCampaignReview()" /></label> |
|
|
<label class="field">Campaign name <input id="campaignName" type="text" maxlength="200" oninput="invalidateCampaignReview()" /></label> |
|
|
<label class="field">Email subject <input id="campaignSubject" type="text" maxlength="240" oninput="invalidateCampaignReview()" /></label> |
|
|
<label class="field">Email subject <input id="campaignSubject" type="text" maxlength="240" oninput="invalidateCampaignReview()" /></label> |
|
|
<label class="field">Template version <select id="campaignTemplateVersion" onchange="invalidateCampaignReview()"></select></label> |
|
|
<label class="field">Template version <select id="campaignTemplateVersion" onchange="invalidateCampaignReview()"></select></label> |
|
|
|
|
|
<h3>Recipients</h3> |
|
|
|
|
|
<label class="field">Filter by email or business <input id="recipientFilter" type="text" oninput="filterRecipients()" /></label> |
|
|
|
|
|
<button onclick="setVisibleRecipients(true)">Select shown</button> |
|
|
|
|
|
<button onclick="setVisibleRecipients(false)">Clear shown</button> |
|
|
|
|
|
<button onclick="refreshRecipients()">Reload contacts</button> |
|
|
|
|
|
<div id="recipientCount"></div> |
|
|
|
|
|
<div style="max-height:220px;overflow:auto;border:1px solid #dbe1e7;background:white"> |
|
|
|
|
|
<table style="margin-top:0"><tbody id="recipientList"></tbody></table> |
|
|
|
|
|
</div> |
|
|
<button onclick="reviewCampaign()">Review message and recipients</button> |
|
|
<button onclick="reviewCampaign()">Review message and recipients</button> |
|
|
<div id="campaignReview"></div> |
|
|
<div id="campaignReview"></div> |
|
|
<iframe id="campaignPreview" APPLICATION="no" title="Full campaign preview"></iframe> |
|
|
<iframe id="campaignPreview" APPLICATION="no" title="Full campaign preview"></iframe> |
|
|
|