Skip to content

Instantly share code, notes, and snippets.

@alexruimy
Last active August 10, 2022 21:50
Show Gist options
  • Select an option

  • Save alexruimy/1a14ac9d0a74ef1816196ffe2c349e15 to your computer and use it in GitHub Desktop.

Select an option

Save alexruimy/1a14ac9d0a74ef1816196ffe2c349e15 to your computer and use it in GitHub Desktop.

Revisions

  1. alexruimy revised this gist Aug 10, 2022. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion email.ts
    Original file line number Diff line number Diff line change
    @@ -48,16 +48,18 @@ abstract class ThreadItem {
    hasMessage: Boolean;
    messageIsCollapsed: Boolean;
    }

    class ThreadItemBanner {
    content: string;
    isInline: Boolean;
    printBanner?(): string;

    constructor(content: string, isInline = false) {
    this.content = content;
    this.isInline = false;
    this.isInline = isInline;
    }
    }

    class ThreadMessage extends ThreadItem {
    type = ThreadMessageType.message;
    content = faker.lorem.sentence(Math.floor(Math.random() * 5) + 1);
  2. alexruimy revised this gist Aug 10, 2022. 1 changed file with 228 additions and 1 deletion.
    229 changes: 228 additions & 1 deletion email.ts
    Original file line number Diff line number Diff line change
    @@ -1 +1,228 @@
    ‎‎
    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 = false;
    }
    }
    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("------");
    });
  3. alexruimy created this gist Aug 10, 2022.
    1 change: 1 addition & 0 deletions email.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    ‎‎