Last active
August 10, 2022 21:50
-
-
Save alexruimy/1a14ac9d0a74ef1816196ffe2c349e15 to your computer and use it in GitHub Desktop.
Email model notes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { faker } from "@faker-js/faker"; | |
// maps to firestore root collection: EmailThread | |
class EmailThread { | |
id: string; | |
eeid: string; // emailengine thread id | |
subject: ThreadSubject; | |
participants: Participants; | |
} | |
class ThreadSubject { | |
default: string; | |
[userId: string]: string; | |
} | |
interface Participants { | |
to: Participant[]; | |
cc?: Participant[]; | |
bcc?: Participant[]; | |
} | |
// map to a Specta user or external contact (eventually, will be part of a Contact model) | |
class Participant { | |
type: "specta" | "external"; | |
userId?: string; | |
email?: string; | |
name?: string; | |
} | |
enum ThreadMessageType { | |
message = "message", | |
suggestion = "suggestion", | |
loopIn = "loopIn", | |
forward = "forward", | |
partialReply = "partialReply", | |
} | |
// subclasses of ThreadItem map to firestore root collection: EmailThreadMessages | |
abstract class ThreadItem { | |
id: string; | |
from: Participant; | |
type: ThreadMessageType; | |
eeid?: string; // emailengine message id | |
participants: Participants; | |
attachments?: []; | |
content?: string; | |
banner?: ThreadItemBanner; | |
hasMessage: Boolean; | |
messageIsCollapsed: Boolean; | |
} | |
class ThreadItemBanner { | |
content: string; | |
isInline: Boolean; | |
printBanner?(): string; | |
constructor(content: string, isInline = false) { | |
this.content = content; | |
this.isInline = isInline; | |
} | |
} | |
class ThreadMessage extends ThreadItem { | |
type = ThreadMessageType.message; | |
content = faker.lorem.sentence(Math.floor(Math.random() * 5) + 1); | |
hasMessage = true; | |
messageIsCollapsed = false; | |
getContent(): Promise<Response> { | |
return fetch(`https://mail.joinspecta.com/api/v1/emails/${this.eeid}`); | |
} | |
} | |
class ThreadSuggestion extends ThreadItem { | |
type = ThreadMessageType.suggestion; | |
hasMessage = false; | |
suggestionTo: Participant; | |
constructor() { | |
super(); | |
const bannerContent = `${this.suggestionTo.name} was suggested to reply by ${this.from.name}`; | |
this.banner = new ThreadItemBanner(bannerContent); | |
} | |
} | |
class ThreadLoopIn extends ThreadItem { | |
type = ThreadMessageType.loopIn; | |
hasMessage = true; | |
messageIsCollapsed = true; | |
loopedIn: Participants[]; | |
formattedParticipants = ""; // todo | |
constructor() { | |
super(); | |
const bannerContent = `${this.formattedParticipants} has been added to the email chain.`; | |
this.banner = new ThreadItemBanner(bannerContent); | |
} | |
} | |
class ThreadForward extends ThreadItem { | |
type = ThreadMessageType.forward; | |
bannerOnly = false; | |
hasMessage = true; | |
messageIsCollapsed = true; | |
formattedParticipants = ""; // todo | |
constructor() { | |
super(); | |
const bannerContent = `Forwarded to ${this.formattedParticipants}`; | |
this.banner = new ThreadItemBanner(bannerContent); | |
} | |
} | |
class ThreadPartialReply extends ThreadItem { | |
type = ThreadMessageType.partialReply; | |
bannerOnly = false; | |
hasBanner = true; | |
hasMessage = true; | |
bannerIsInline = true; | |
messageIsCollapsed = false; | |
formattedParticipants = ""; // todo | |
constructor() { | |
super(); | |
const bannerContent = `Reply to ${this.formattedParticipants}`; | |
this.banner = new ThreadItemBanner(bannerContent, true); | |
} | |
} | |
/// BELOW HERE I JUST PLAYED WITH GENERATING AN EMAIL THREAD, PROBABLY NOTHING TO SEE HERE | |
const getChoiceFromArray = (array: any[]) => | |
array[Math.floor(Math.random() * array.length)]; | |
// fetch email content from emailengine | |
const urlprefix = "https://mail.joinspecta.com/"; | |
const getEmailContent = async (eeid: string) => { | |
const response = await fetch(`${urlprefix}api/v1/threads/${eeid}`); | |
const data = await response.json(); | |
return data; | |
}; | |
function getThreadItem(): ThreadItem { | |
const random = Math.random(); | |
let threadItem; | |
if (random < 0.4) { | |
threadItem = new ThreadMessage(); | |
} else { | |
const randomType = Math.floor(Math.random() * 4); | |
switch (randomType) { | |
case 0: | |
threadItem = new ThreadSuggestion(); | |
case 1: | |
threadItem = new ThreadLoopIn(); | |
case 2: | |
threadItem = new ThreadForward(); | |
case 3: | |
threadItem = new ThreadPartialReply(); | |
} | |
} | |
threadItem.id = faker.datatype.uuid(); | |
return threadItem; | |
} | |
let participants = Array(); | |
for (let i = 0; i < 4; i++) { | |
let p = <Participant>{ | |
type: getChoiceFromArray(["specta", "external"]), | |
userId: faker.datatype.uuid(), | |
email: faker.internet.email(), | |
name: faker.name.fullName(), | |
}; | |
participants.push(p); | |
} | |
let ps = <Participants>{ to: participants }; | |
// create an array of 20 messages. | |
// instantiate each message with getThreadMessage() | |
// if message is a message | |
let messages = Array(); | |
for (let i = 0; i < 10; i++) { | |
let currentUser = getChoiceFromArray(participants); | |
let recipient = getChoiceFromArray( | |
participants.filter((p) => p !== currentUser) | |
); | |
let m = getThreadItem(); | |
m.from = currentUser; | |
m.participants = ps; | |
messages.push(m); | |
} | |
// messages.push(m); | |
// console.log(messages); | |
// todo: add normalizer for thread id | |
let thread = <EmailThread>{ | |
id: "1", | |
eeid: "1", | |
subject: { default: "Hello" }, | |
participants: ps, | |
}; | |
let messageCount = 0; | |
messages.forEach((m) => { | |
if (m.type === ThreadMessageType.message) { | |
messageCount++; | |
console.log("MESSAGE " + messageCount); | |
console.log( | |
"TO: " + | |
m.participants.to.map((p: Participant) => p.email).join(", ") | |
); | |
console.log("FROM: " + m.from.email); | |
console.log(m.content); | |
} else { | |
console.log(m.banner.toUpperCase()); | |
if (!m.bannerOnly) { | |
console.log( | |
m.from.name, | |
m.participants.to.map((p: Participant) => p.name).join(", ") | |
); | |
} | |
} | |
console.log("------"); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment