Skip to content

Instantly share code, notes, and snippets.

@alexmanzo
Last active January 17, 2019 02:20
Show Gist options
  • Save alexmanzo/7fe68db12ea9f17c7318987ada66e533 to your computer and use it in GitHub Desktop.
Save alexmanzo/7fe68db12ea9f17c7318987ada66e533 to your computer and use it in GitHub Desktop.
import AlertModal from "../AlertModal.vue";
import DoughnutChart from "../DoughnutChart.js";
import Navigation from "../Navigation.vue";
import { mapState } from "vuex";
import moment from "moment";
const BrandConfig = require("../../utils/BrandConfig.js");
const ParseUtils = require("../../utils/ParseUtils.js");
const Tools = require("../../utils/Tools.js");
// This code comes from the <script> section of a Vue component.
//It imports other components to render the user's licenses dashboard .
export default {
// Bring in components to use in template
components: { AlertModal, DoughnutChart, Navigation },
data() {
// Initial state for data used in template
return {
confirmRecall: false,
selectedLicense: undefined,
performingRequest: false,
boolVal: false,
overviewExamFilterName: "All Exams",
detailsExamFilterName: "All Exams",
detailsStatusFilterName: "All",
emailSearch: "",
statusFilters: ["Available", "Consumed", "Pending"],
paginate: ["licenses"],
showDetailsExamFilters: false,
showDetailsStatusFilters: false,
showOverviewExamFilters: false,
assigningLicenseAtIndex: null,
emailToAssign: null,
showAssignSuccess: false
};
},
computed: {
// Return array exams which have licenses purchased.
examFilters() {
let exams = [];
// Pulls licences from state (Vuex)
let licenses = this.$store.state.purchasedExams;
licenses.forEach(item => {
if (!exams.includes(item.examName)) {
exams.push(item.examName);
}
});
return exams.sort();
},
// Will update DoughnutChart component with breakdown of license statuses
chartData() {
// Pull # of available licenses from state (Vuex)
let available = this.$store.state.purchasedExams.filter(item => {
if (this.overviewExamFilterName == "All Exams") {
// Returns all exams with status of available
return item.status == "available";
} else {
// Returns available exams based on filterName - ie. If filter name == 'ACSM CPT', would only return available exams with that name.
return (
item.status == "available" &&
item.examName == this.overviewExamFilterName
);
}
}).length;
// Pull # of consumed licenses from state (Vuex)
let consumed = this.$store.state.purchasedExams.filter(item => {
if (this.overviewExamFilterName == "All Exams") {
// Returns all exams with status of consumed
return item.status == "consumed";
} else {
// Returns consumed exams based on filterName - ie. If filter name == 'ACSM CPT', would only return consumed exams with that name.
return (
item.status == "consumed" &&
item.examName == this.overviewExamFilterName
);
}
}).length;
// Pull # of pending licenses from state (Vuex)
let pending = this.$store.state.purchasedExams.filter(item => {
if (this.overviewExamFilterName == "All Exams") {
// Returns all exams with status of pending
return item.status == "pending";
} else {
// Returns pending exams based on filterName - ie. If filter name == 'ACSM CPT', would only return pending exams with that name.
return (
item.status == "pending" &&
item.examName == this.overviewExamFilterName
);
}
}).length;
// Notes: available, consumed, pending variables all contain repeating code. Would be better served to created a method of filtering through exams and passing status as a parameter.
// For example:
// let pending = this.filterExams(available)
// filterExams(status) {
// this.$store.state.purchasedExams.filter(item => {
// if (this.overviewExamFilterName == status) {
// return item.status == status;
// } else {
// return (
// item.status == status &&
// item.examName == this.overviewExamFilterName
// );
// }
// }).length;
//} ^^ Or something to this effect.
return {
total: available + consumed + pending,
available: available,
consumed: consumed,
pending: pending
};
// // Could also simplify this object to be {
// total: available + consumed + pending,
// available,
// consumed,
// pending
// }
},
licenses() {
// Will update list of exams under 'license detail's' based on filters
let licenseArray = this.$store.state.purchasedExams;
// detailsExamFilterName -- filtering by Exam (leftmost column)
// detailsStatusFilterName -- filtering by status (status column)
// Both filters set to all
if (
this.detailsExamFilterName == "All Exams" &&
this.detailsStatusFilterName == "All"
) {
// If no e-mail search entered, return entire array
if (this.emailSearch == "") {
return licenseArray;
}
// Return array based on if license includes searched e-mail string.
return licenseArray.filter(item => {
if (item.userEmail) {
return item.userEmail.includes(this.emailSearch);
}
});
// Status given, Exam name set to all
} else if (
this.detailsStatusFilterName !== "All" &&
this.detailsExamFilterName == "All Exams"
) {
if (this.emailSearch == "") {
// return items with specificed status
return licenseArray.filter(item => {
return item.status == this.detailsStatusFilterName.toLowerCase();
});
}
return licenseArray.filter(item => {
if (item.userEmail) {
return (
// return items with specificed status & email
item.status == this.detailsStatusFilterName.toLowerCase() &&
item.userEmail.includes(this.emailSearch)
);
}
});
// Exam name given, status filter set to all
} else if (
this.detailsStatusFilterName == "All" &&
this.detailsExamFilterName !== "All Exams"
) {
if (this.emailSearch == "") {
// return items with specificed exam name
return licenseArray.filter(item => {
return item.examName == this.detailsExamFilterName;
});
}
// return items with specificed status and email
return licenseArray.filter(item => {
if (item.userEmail) {
return (
item.examName == this.detailsExamFilterName &&
item.userEmail.includes(this.emailSearch)
);
}
});
// Specific exam name and specific filter given
} else {
if (this.emailSearch == "") {
return licenseArray.filter(item => {
return (
// return items with specificed status & specificed exam name
item.examName == this.detailsExamFilterName &&
item.status == this.detailsStatusFilterName.toLowerCase()
);
});
}
return licenseArray.filter(item => {
if (item.userEmail) {
return (
// return items with specificed status, specificed exam name, and specifided e-mail
item.examName == this.detailsExamFilterName &&
item.status == this.detailsStatusFilterName.toLowerCase() &&
item.userEmail.includes(this.emailSearch)
);
}
});
}
// Notes: This again contains a lot of repeating code. Additionally, such a long if Else statement leads to more potential for bugs, limitations in scalability, and makes code harder to read.
// Ideally, this could be condensed into one filter function, which would take an array of filters as an argument. Similar to:
// let examFilter;
// let statusFilter;
// let emailFilter;
// let activeFilters = [];
// if (this.detailsExamFilterName !== "All Exams") {
// examFilter = this.detailsExamFilterName
// activeFilters.push(examFilter)
// }
// if (this.detailsStatusFilterName !== "All") {
// statusFilter = this.detailsStatusFilterName
// activeFilters.push(statusFilter)
// }
// if (this.emailSearch !== '') {
// emailFilter = this.emailSearch
// activeFilters.push(emailFilter)
// }
// function filter(arr, criteria) {
// return arr.filter(item => {
// return Object.keys(criteria).every(key => {
// return item[key] == criteria[key];
// });
// });
// }
// filter(licenseArray, activeFilters)
// ^^ This is an untested solution, but gets to basic idea of cutting down on long, nested if/else statements and repetitive code.
},
methods: {
examFilterSelected(cellName, exam) {
if (cellName == "overview") {
this.overviewExamFilterName = exam;
this.showOverviewExamFilters = false;
} else if (cellName == "details") {
this.detailsExamFilterName = exam;
this.showDetailsExamFilters = false;
}
},
statusFilterSelected(status) {
this.detailsStatusFilterName = status;
this.showDetailsStatusFilters = false;
},
isExpiredLicense(expirationDate) {
if (!expirationDate) {
return;
}
let today = new Date();
let licenseDate = new Date(expirationDate.iso);
if (today.getTime() > licenseDate.getTime()) {
return true;
}
},
showAssignLicenseAtIndex(index) {
this.assigningLicenseAtIndex = index;
},
assignLicense(item) {
if (!Tools.isEmailAddressValid(this.emailToAssign)) {
return;
}
var appId = item.appId;
var emailAddresses = [this.emailToAssign.toLowerCase()];
var bulkPurchaserId = item.bulkPurchaser.objectId;
ParseUtils.assignLicensesTo(appId, bulkPurchaserId, emailAddresses).then(
assignedLicense => {
// intercom event
window.Intercom("trackEvent", "Assigned License Dashboard");
gtag("event", "dashboard_assign", {
event_category: "assign_license",
event_label: appId
});
item.userEmail = emailAddresses[0];
item.status = "pending";
this.clearAssignLicenseFields();
}
);
},
resendLicense(item) {
if (item.userEmail == null) {
return;
}
var attributes = {
appId: item.appId,
company: this.$store.state.user.get("company"),
email: item.userEmail.toLowerCase(),
examName: item.examName,
licenseKey: item.licenseKey
};
ParseUtils.resendLicense(attributes).then(success => {
// intercom event
window.Intercom("trackEvent", "Resent Invite");
if (success == true) {
this.showAssignSuccess = true;
setTimeout(() => {
this.showAssignSuccess = false;
}, 4000);
}
});
},
cancelAssign() {
this.clearAssignLicenseFields();
},
clearAssignLicenseFields() {
this.assigningLicenseAtIndex = null;
this.emailToAssign = null;
},
cancelInvite(item) {
ParseUtils.cancelInvite(item.licenseKey).then(license => {
// intercom event
window.Intercom("trackEvent", "Cancelled Invite");
item.userEmail = null;
item.status = "available";
});
},
formatPrice(val) {
val = val.toString();
val = val.slice(0, -2) + "." + val.slice(-2);
// val = '$' + val.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")
return val;
},
exportLicenseDetails() {
var csv = "Exam,User,License Key,Status,ExpirationDate\n";
var dateString = "";
this.licenses.forEach(license => {
if (license.expirationDate && license.expirationDate.iso) {
var date = new Date(license.expirationDate.iso);
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dt = date.getDate();
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
if (dt < 10) {
dt = "0" + dt;
}
if (month < 10) {
month = "0" + month;
}
if (hour < 10) {
hour = "0" + hour;
}
if (minute < 10) {
minute = "0" + minute;
}
if (second < 10) {
second = "0" + second;
}
dateString =
year +
"-" +
month +
"-" +
dt +
" " +
hour +
":" +
minute +
":" +
second;
} else {
dateString = "";
}
var data = [
license.examName,
license.userEmail,
license.licenseKey,
license.status,
dateString
];
csv += data.join(",");
csv += "\n";
});
// Prior method did not work in Safari, this does
// https://github.com/mholt/PapaParse/issues/175
const blob = new Blob([csv]);
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, "license-details.csv");
} else {
var a = window.document.createElement("a");
a.href = window.URL.createObjectURL(blob, {
type: "text/csv;charset=utf-8"
});
a.download = "license-details.csv";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
},
recallSelectedLicense() {
return ParseUtils.recallLicense(
this.selectedLicense.licenseKey,
true
).then(_ => {
// intercom event
window.Intercom("trackEvent", "Recalled License");
this.dismissRecallConfirmation();
// go fetch the updated license info
this.$store.dispatch("getPurchasedExams");
});
},
showRecallConfirmation(item) {
(this.selectedLicense = item), (this.confirmRecall = true);
},
dismissRecallConfirmation() {
// clear out our local state
this.confirmRecall = false;
this.selectedLicense = undefined;
}
},
filters: {
formateDate(val) {
if (!val) {
return "-";
}
return moment(val.iso).calendar();
}
},
mounted() {
// intercom updates
let user = this.$store.state.user;
let metaData = this.$store.state.userMetaData;
if (user && metaData) {
let appNames = "";
let exams = [];
metaData.exams.forEach(exam => {
appNames = appNames + exam.name + ", ";
exams.push(exam.name);
});
let totalSpent = this.formatPrice(metaData.subtotal);
let numOfExams = Array.from(new Set(exams));
console.log(metaData);
const attributes = {
Company: user.get("company"),
"Has made a purchase": metaData.subtotal > 0 ? "Yes" : "No",
"Number of Purchases Made": metaData.numberOfPurchasesMade,
"Total Spent": totalSpent,
"Number of licenses purchased / received": metaData.totalNumOfLicenses,
"Number of licenses available": this.chartData.available,
"Number of licenses pending": this.chartData.pending,
"Number of licenses redeemed": this.chartData.consumed,
"App Names": appNames,
"Number of exams": numOfExams.length,
"Has Received Gifted Licenses": metaData.attachedLicenseCount
? "Yes"
: "No"
};
window.intercomSettings = {
email: user.get("email"),
name: user.get("firstName") + " " + user.get("lastName"),
user_id: user.id
};
window.Intercom("update", attributes);
window.Intercom("trackEvent", "Viewed Dashboard");
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment