feat: move all email to defer queue #185
fix: use relative part for defer func #185 chore: move sendEmail into defer fix: remove anon function to defer #185 feat: implement batch email sending with defer.run #185 chore: debug sendEmails #185 chore: add robots.txt chore: use promise.all in sendEmails chore: debug defer sendEmails #185 chore: try defer sendEmail without loop #105 chore: comment code chore: change loop style #185 chore: use promise.all for vercel edge #185 feat: add await to sendEmailNotification #185 chore: use sendEmails #185 fix: debug sendEmails #185 fix: email not updating in LMS fix: remove early return in sendEmails #185
This commit is contained in:
@@ -67,12 +67,7 @@
|
||||
id: createdFeed.id,
|
||||
content: newPost,
|
||||
author: {
|
||||
profile: {
|
||||
id: author.id,
|
||||
username: author.username,
|
||||
fullname: author.fullname,
|
||||
avatar_url: author.avatar
|
||||
}
|
||||
profile: { ...author }
|
||||
},
|
||||
created_at: createdFeed.created_at,
|
||||
comment: [],
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
export let feed: Feed;
|
||||
export let editFeed: Feed | any = {};
|
||||
export let author: Author | any = {};
|
||||
export let editFeed: Feed;
|
||||
export let author: Author;
|
||||
export let edit = false;
|
||||
export let deleteFeed = (arg: string) => {};
|
||||
export let deleteComment = (arg: string) => {};
|
||||
@@ -70,6 +70,14 @@
|
||||
deleteComment(id);
|
||||
};
|
||||
|
||||
const getClassIfSelectedByAuthor = (reactionType) => {
|
||||
const usersReacted = feed.reaction[reactionType] || [];
|
||||
|
||||
return usersReacted.includes(author.id)
|
||||
? 'bg-primary-200 border-primary-600 pl-2'
|
||||
: 'bg-gray-200 border-gray-600 pl-2';
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
if (isActive) {
|
||||
const el = document.getElementById(feed.id);
|
||||
@@ -94,13 +102,13 @@
|
||||
<span class="flex items-center gap-3">
|
||||
<div class="w-9 h-9">
|
||||
<img
|
||||
src={feed.author?.profile.avatar_url}
|
||||
src={feed.author?.profile?.avatar_url}
|
||||
alt="users banner"
|
||||
class="w-full h-full rounded-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<span>
|
||||
<p class="text-base font-semibold capitalize">{feed.author?.profile.fullname}</p>
|
||||
<p class="text-base font-semibold capitalize">{feed.author?.profile?.fullname}</p>
|
||||
<p class="text-sm font-medium text-gray-600">{calDateDiff(feed.created_at)}</p>
|
||||
</span>
|
||||
</span>
|
||||
@@ -134,7 +142,7 @@
|
||||
on:click={() => handleAddNewReaction(reactionType)}
|
||||
class={`flex transition ${
|
||||
feed.reaction[reactionType].length >= 1 &&
|
||||
'bg-primary-200 dark:bg-gray-900 dark:text-black px-1 border border-primary-600 rounded-full'
|
||||
`${getClassIfSelectedByAuthor(reactionType)} dark:text-black border rounded-full`
|
||||
}`}
|
||||
>
|
||||
<div class="text-[15px]">{reactions[reactionType]}</div>
|
||||
@@ -197,7 +205,7 @@
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="w-7 h-7">
|
||||
<img
|
||||
src={author.avatar}
|
||||
src={author.avatar_url}
|
||||
alt="users banner"
|
||||
class="w-full h-full rounded-full object-cover"
|
||||
/>
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
|
||||
const updates = {
|
||||
fullname: $profile.fullname,
|
||||
username: $profile.username
|
||||
username: $profile.username,
|
||||
email: $profile.email
|
||||
};
|
||||
|
||||
if (avatar) {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import type { Course } from '$lib/utils/types';
|
||||
import { supabase } from '$lib/utils/functions/supabase';
|
||||
import type { Reaction, FeedApi } from '$lib/utils/types/feed';
|
||||
import type { Reaction, FeedApi, Feed } from '$lib/utils/types/feed';
|
||||
|
||||
export async function fetchNewsFeedReaction(feedId: Feed['id']) {
|
||||
return supabase.from('course_newsfeed').select(`reaction`).eq('id', feedId).single();
|
||||
}
|
||||
|
||||
export async function fetchNewsFeeds(courseId?: Course['id']) {
|
||||
const response = await supabase
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import nodemailer from 'nodemailer';
|
||||
import { withEmailTemplate } from './template';
|
||||
import {
|
||||
SMTP_HOST,
|
||||
SMTP_USER,
|
||||
@@ -10,8 +9,19 @@ import {
|
||||
|
||||
let transporter: nodemailer.Transporter;
|
||||
|
||||
const getTransporter = async (isPersonal?: boolean): Promise<boolean> => {
|
||||
export const getTransporter = async (
|
||||
isPersonal?: boolean
|
||||
): Promise<nodemailer.Transporter | null> => {
|
||||
return await new Promise((resolve, reject) => {
|
||||
// If email sending isn't configured
|
||||
if (!SMTP_HOST) {
|
||||
resolve(null);
|
||||
}
|
||||
|
||||
if (transporter) {
|
||||
return resolve(transporter);
|
||||
}
|
||||
|
||||
transporter = nodemailer.createTransport({
|
||||
host: SMTP_HOST,
|
||||
port: 465,
|
||||
@@ -22,49 +32,14 @@ const getTransporter = async (isPersonal?: boolean): Promise<boolean> => {
|
||||
}
|
||||
});
|
||||
|
||||
transporter.verify(function (error, success) {
|
||||
transporter.verify(function (error) {
|
||||
if (error) {
|
||||
console.log('Transporter error', error);
|
||||
reject(error);
|
||||
reject(null);
|
||||
} else {
|
||||
console.log('Server is ready to take our messages');
|
||||
resolve(success);
|
||||
resolve(transporter);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const sendEmail = async ({
|
||||
from,
|
||||
to,
|
||||
subject,
|
||||
content,
|
||||
isPersonalEmail,
|
||||
replyTo
|
||||
}: {
|
||||
from?: string;
|
||||
to: string;
|
||||
subject: string;
|
||||
content: string;
|
||||
isPersonalEmail?: boolean;
|
||||
replyTo?: string;
|
||||
}) => {
|
||||
try {
|
||||
await getTransporter(isPersonalEmail);
|
||||
const info = await transporter.sendMail({
|
||||
from: from || '"Best from ClassroomIO" <[email protected]>', // sender address
|
||||
to, // list of receivers
|
||||
subject, // Subject line
|
||||
replyTo,
|
||||
html: withEmailTemplate(content) // html body
|
||||
});
|
||||
|
||||
console.log('Message sent: %s', info.messageId);
|
||||
|
||||
return info;
|
||||
} catch (error) {
|
||||
console.error({ error });
|
||||
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ export interface FeedApi {
|
||||
};
|
||||
created_at: string;
|
||||
comment: Comment[];
|
||||
reaction: Reaction[];
|
||||
reaction: Reaction;
|
||||
is_pinned: false;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,6 @@ export interface Feed {
|
||||
};
|
||||
created_at: string;
|
||||
comment: Comment[];
|
||||
reaction: Reaction[];
|
||||
reaction: Reaction;
|
||||
isPinned: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user