Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,579 changes: 1,443 additions & 136 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"http-errors": "~1.6.2",
"jszip": "^3.1.5",
"morgan": "~1.9.0",
"pug": "2.0.0-beta11"
"node-sass": "^4.9.0",
"pug": "^2.0.0-beta11",
"vue": "^2.5.16",
"vue-select": "^2.4.0"
}
}
Binary file modified public/.DS_Store
Binary file not shown.
4 changes: 3 additions & 1 deletion public/scripts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ document.addEventListener("DOMContentLoaded", () => {
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);
});
});

//checkForReport();
79 changes: 67 additions & 12 deletions public/scripts/util/CSVParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,31 @@ function CSVToJSONConverter(Blob, callback) {

let headers = lines.filter(line => line.length > 1)[0];

//loop through entries (proceeding the headers)
//help from http://techslides.com/convert-csv-to-json-in-javascript
lines.filter(line => line.length > 1)
.slice(1)
.forEach(line => {
let entry = {};
//check if the CSV is the overview; headers will be different.
//detected by seeing if the very first line has more than one column
if (headers === lines[0]) {
json = OverviewCSVtoJSON(lines, json);
}
//if it's not the overview, parse normally
else {
json = CSVtoJSON(lines, json, headers);
}

//json.shift(); headers are already removed above

callback(json, lines.filter(line => line.length === 1 && line[0] !== ""));
};

//set the file reader to read the contents as text
reader.readAsText(Blob);
}

function CSVtoJSON(lines, json, headers) {
//loop through entries (proceeding the headers)
lines.filter(line => line.length > 1)
.slice(1) //remove the headers
.forEach(line => {
let entry = {};

//loop through columns
for(let j = 0; j < headers.length; j++) {
Expand All @@ -54,20 +72,57 @@ function CSVToJSONConverter(Blob, callback) {

json.push(entry);
});
return json;
}

json.shift();
function OverviewCSVtoJSON(lines, json) {

callback(json, lines.filter(line => line.length === 1 && line[0] !== ""));
};
//loop through entries
for (let i = 0; i < lines.length; i++) {
let entry = {};

//set the file reader to read the contents as text
reader.readAsText(Blob);
//remove colons that are at the end of the string
for(let k = 0; k < lines[i].length; k++) {
if (lines[i][k][lines[i][k].length - 1] === ":") {
lines[i][k] = lines[i][k].substring(0, lines[i][k].length - 1);
}
}

//check if line is just a header
//determined by: either it only has one column, OR the second column is empty (and the first column is not empty)
if ((lines[i].length === 1 && lines[i][0].length > 2) || (lines[i][0].length > 1 && lines[i][1] === "")) {
let subJson = {};
let j = i + 1;
for (; j < lines.length; j++) {
if (lines[j][0].length < 3){
break;
}
subJson[j - (i + 1)] = lines[j];
lines[j] = "";
}
entry[lines[i]] = subJson;
i = j - 1;
//json.push(entry); //move to below if/else if we want to see the gaps in the CSV file
}
//otherwise, proceed to make json entry as normal
else if (lines[i].length > 1) {
//console.log("" + lines[i][0] + " length is: " + lines[i].length);
entry[lines[i][0]] = lines[i][1];

//json.push(entry); //move to below if/else if we want to see the gaps in the CSV file
}

json.push(entry);
}

return json;
}

function processData(data, metadata) {
console.log(metadata);
console.log(data)
console.log(data);

generateReport(data);
}

/*
Expand Down
154 changes: 154 additions & 0 deletions public/scripts/util/vueScripts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@

Vue.component('initial-box', {
data: function () {
return {
header: "Welcome to the Email Report Generator",
text: "Upload a csv file of an email to get started.",
}
},
template: '<div><h1 class="drop-box-text">{{ header }}</h1><p>{{ text }}</p></div>'
});

Vue.component('standard-box', {
data: function () {
return {
text: "Drag and drop to upload an additional email"
}
},
template: '<p>{{ text }}</p>'
});

let dropBox = new Vue({
el: '#drop-box',
data: {
currentBox: 'initial-box',
styling: {
"padding": '30%',
"background": 'radial-gradient(#0e76a3, #0d56a2, #0d2b56)'
}
}
});

let emailReport = new Vue({
el: '#emails',
data: {
showReports: "none",
reports: [],
currentCampaign: null,
currentDate: null
},
computed: {
//variable called that will determine if the email is old data and needs to be updated
needsUpdating: function () {
if (this.currentCampaign === null || this.currentDate === null) return false;
let date = new Date(this.reports[this.currentDate].emails[this.currentCampaign].report["Sent"]);
return (date.toDateString() !== new Date().toDateString());
},
emailsPerDate: function() {
if (this.currentDate !== null){
return this.reports[this.currentDate].emails;
}
return [];

},
currentReport: function() {
if (this.currentDate !== null && this.currentCampaign !== null) {
return this.reports[this.currentDate].emails[this.currentCampaign].report;
}
return [];
}
},
methods: {
//function to determine if the second element of a key-value pair is an array or just a string value
isString: function (value) {
if (!value) return true;
return (Object.getOwnPropertyNames(value)[Object.getOwnPropertyNames(value).length - 1] === "length")
}
},
filters: {
//remove the quotations from a value (in an array)
formatItem: function (item) {
return item.replace(/"/g, "");
}
},
watch: {
//watch campaigns and whenever it changes (a new report is uploaded and parsed), store to local storage
reports: function (newCampaignArray, oldCampaignArray) {

localStorage.setItem('emailGeneratorReports', JSON.stringify(this.reports));

this.showReports = "block";
}
}
});


//change the dropbox depending on if any emails have been uploaded
emailReport.$watch('reports', function (newValue, oldValue) {
dropBox.currentBox = 'standard-box';
dropBox.styling = {
"padding": "1%",
"background": 'linear-gradient(-90deg, #0d2b56, #0d56a2, #0e76a3)'
};
});


function generateReport(data) {

let content = {};
data.forEach(line => {
for (let key in line) {
content[key] = line[key];
}
});


//new data structure

let report = {};
let found = false;
report["name"] = content["Campaign"];
report["service"] = "myEmma";
report["report"] = content;

//check if there are other emails from this date
let reportDate = new Date(content["Sent"]).toDateString();
emailReport.reports.forEach(dateGroup => {
if (new Date(dateGroup["date"]).toDateString() === reportDate) {
dateGroup["emails"].push(report);
found = true;
}
});

//if this is the first email for this date, create new entry
if (!found) {
let dateGroup = {};
dateGroup["date"] = content["Sent"];
dateGroup["emails"] = [report];
emailReport.reports.push(dateGroup);
}

console.log("reports (new data structure): ");
console.log(emailReport.reports);
}

//check local storage for previous data
function checkForReport() {

if (typeof(Storage) !== "undefined") {

//check if past emails have been stored
if(localStorage.getItem("emailGeneratorReports")) {
//if so, load them into Vue vars
// localStorage.removeItem('emailGeneratorReports');

emailReport.reports = JSON.parse(localStorage.getItem("emailGeneratorReports"));
}

} else {
//local storage not supported
}
}

//run this function upon initialization to fetch data from local storage
checkForReport();
88 changes: 88 additions & 0 deletions public/styles/css/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
html {
font-family: 'Catamaran', sans-serif;
}

div#drop-box {
padding: 1rem 2rem;
background-color: #236192;
color: #fff;
}

div.alert {
background-color: #ffcf16;
padding: 3px;
}

div#emails {
margin: 2rem;
}

div#emails select {
margin-bottom: 1rem;
}

div#reports {
display: flex;
}

div.buttons {
text-align: center;
border-top: 1px solid #9fa7ad;
}

div.buttons button {
padding: 1rem;
display: block;
border-style: solid;
border-color: gray;
border-width: 0 0 1px 1px;
width: 10rem;
}

div.report {
display: flex;
flex-flow: column;
border: 1px solid gray;
width: 100%;
box-sizing: border-box;
}

table {
background-color: #e0eef9;
}

th, td {
display: block;
padding: 3px;
text-align: left;
vertical-align: top;
}

th {
width: 30%;
}

td {
max-width: 69%;
}

td div {
display: flex;
}

td div p {
padding: 6px;
margin: 0 0 0 0;
border: 1px solid #9fa7ad;
border-radius: 10px;
background-color: #edf7ff;
}

td#alertDate {
color: #ffcf16;
}

tr {
display: flex;
border-bottom: 1px solid #9fa7ad;
}
File renamed without changes.
6 changes: 0 additions & 6 deletions public/styles/index.css

This file was deleted.

4 changes: 0 additions & 4 deletions public/styles/index.sass

This file was deleted.

Loading