You've already forked obsidian-visualiser
Fix Campaign log DB and rendering. Migrate mail rendering to virtual DOM API.
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { dom } from '#shared/dom';
|
||||
import { dom, type VirtualNode } from "#shared/dom.virtual.util";
|
||||
|
||||
export default function(content: HTMLElement[])
|
||||
export default function(content: VirtualNode[])
|
||||
{
|
||||
return [dom('div', { style: 'margin-left: auto; margin-right: auto; width: 75%; font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 1rem; line-height: 1.5rem; color: #171717;' }, [
|
||||
dom('div', { style: 'margin-left: auto; margin-right: auto; text-align: center;' }, [
|
||||
dom('a', { style: 'display: inline-block;', attributes: { href: 'https://d-any.com' } }, [
|
||||
dom('img', { style: 'display: block; height: 4rem; width: 4rem; margin-left: auto; margin-right: auto;', attributes: { src: 'https://d-any.com/logo.light.png', alt: 'Logo', title: 'd[any] logo', width: '64', height: '64' } })
|
||||
dom('img', { style: 'display: block; height: 4rem; width: 4rem; margin-left: auto; margin-right: auto;', attributes: { src: 'https://d-any.com/logo.light.png', alt: 'Logo', title: 'd[any] logo', width: '64', height: '64' } }),
|
||||
dom('span', { style: `margin-inline-end: 1rem; font-size: 1.5rem; color: black; text-decoration: none; line-height: 2rem; font-weight: 700; font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;`, text: 'd[any]' })
|
||||
])
|
||||
]),
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<template>
|
||||
<div style='margin-left: auto; margin-right: auto; width: 75%; font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 1rem; line-height: 1.5rem; color: #171717;'>
|
||||
<div style="margin-left: auto; margin-right: auto; text-align: center;">
|
||||
<a style="display: inline-block;" href="https://d-any.com">
|
||||
<img src="https://d-any.com/logo.light.png" alt="Logo" title="d[any] logo" width="64" height="64" style="display: block; height: 4rem; width: 4rem; margin-left: auto; margin-right: auto;" />
|
||||
<span style="margin-inline-end: 1rem; font-size: 1.5rem; color: black; text-decoration: none; line-height: 2rem; font-weight: 700; font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;">d[any]</span>
|
||||
</a>
|
||||
</div>
|
||||
<div style="padding: 1rem;">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div style="background-color: #171717;">
|
||||
<p style="padding-top: 1rem; padding-bottom: 1rem; text-align: center; font-size: 0.75rem; line-height: 1rem; color: #fff;">Copyright Peaceultime / d[any] - 2024 / 2025</p>
|
||||
</div>
|
||||
</template>
|
||||
18
server/components/mail/registration.ts
Normal file
18
server/components/mail/registration.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { dom, text } from "#shared/dom.virtual.util";
|
||||
|
||||
export default function(data: any)
|
||||
{
|
||||
const hash = Bun.hash('1' + data.userId.toString(), data.timestamp);
|
||||
return [dom('div', { style: 'max-width: 800px; margin-left: auto; margin-right: auto;' }, [
|
||||
dom('p', { style: 'font-variant: small-caps; margin-bottom: 1rem; font-size: 1.25rem; line-height: 1.75rem;' }, [ text(`Bienvenue sur d[any], `), dom('span', { style: '' }, [ text(data.username) ]) ]),
|
||||
dom('p', { style: '' }, [ text(`Nous vous invitons à valider votre compte afin de profiter de toutes les fonctionnalités de d[any].`) ]),
|
||||
dom('div', { style: 'padding-top: 1rem; padding-bottom: 1rem; text-align: center;' }, [
|
||||
dom('a', { attributes: { href: `https://d-any.com/user/mailvalidation?u=${data.userId}&i=${data.id}&t=${data.timestamp}&h=${hash}`, target: '_blank' } }, [ dom('span', { style: 'display: inline-block; border-width: 1px; border-color: #525252; background-color: #e5e5e5; padding-left: 0.75rem; padding-right: 0.75rem; padding-top: 0.25rem; padding-bottom: 0.25rem; font-weight: 200; color: #171717; text-decoration: none;' }, [ text('Je valide mon compte') ]) ]),
|
||||
dom('span', { style: 'display: block; padding-top: 0.5rem; font-size: 0.75rem; line-height: 1rem;' }, [ text('Ce lien est valable 1 heure.') ])
|
||||
]),
|
||||
dom('div', { style: '' }, [
|
||||
dom('span', { style: '' }, [ text('Vous pouvez egalement copier le lien suivant pour valider votre compte: ') ]),
|
||||
dom('pre', { style: 'display: inline-block; border-bottom-width: 1px; font-size: 0.75rem; line-height: 1rem; color: #171717; font-weight: 400; text-decoration: none;' }, [ text(`https://d-any.com/user/mailvalidation?u=${data.userId}&i=${data.id}&t=${data.timestamp}&h=${hash}`) ])
|
||||
])
|
||||
])];
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<template>
|
||||
<div style="max-width: 800px; margin-left: auto; margin-right: auto;">
|
||||
<p style="font-variant: small-caps; margin-bottom: 1rem; font-size: 1.25rem; line-height: 1.75rem;">Bienvenue sur d[any], <span>{{ username }}</span>.</p>
|
||||
<p>Nous vous invitons à valider votre compte afin de profiter de toutes les fonctionnalités de d[any].</p>
|
||||
<div style="padding-top: 1rem; padding-bottom: 1rem; text-align: center;">
|
||||
<a :href="`https://d-any.com/user/mailvalidation?u=${userId}&i=${id}&t=${timestamp}&h=${hash}`" target="_blank"><span style="display: inline-block; border-width: 1px; border-color: #525252; background-color: #e5e5e5; padding-left: 0.75rem; padding-right: 0.75rem; padding-top: 0.25rem; padding-bottom: 0.25rem; font-weight: 200; color: #171717; text-decoration: none;">Je valide mon compte</span></a>
|
||||
<span style="display: block; padding-top: 0.5rem; font-size: 0.75rem; line-height: 1rem;">Ce lien est valable 1 heure.</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Vous pouvez egalement copier le lien suivant pour valider votre compte: </span>
|
||||
<pre style="display: inline-block; border-bottom-width: 1px; font-size: 0.75rem; line-height: 1rem; color: #171717; font-weight: 400; text-decoration: none;">{{ `https://d-any.com/user/mailvalidation?u=${userId}&i=${id}&t=${timestamp}&h=${hash}` }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import Bun from 'bun';
|
||||
|
||||
const { id, userId, username, timestamp } = defineProps<{
|
||||
id: number
|
||||
userId: number
|
||||
username: string
|
||||
timestamp: number
|
||||
}>();
|
||||
const hash = computed(() => Bun.hash('1' + userId.toString(), timestamp));
|
||||
</script>
|
||||
19
server/components/mail/reset-password.ts
Normal file
19
server/components/mail/reset-password.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { dom, text } from "#shared/dom.virtual.util";
|
||||
|
||||
export default function(data: any)
|
||||
{
|
||||
const hash = Bun.hash('1' + data.userId.toString(), data.timestamp);
|
||||
return [dom('div', { style: 'max-width: 800px; margin-left: auto; margin-right: auto;' }, [
|
||||
dom('p', { style: 'font-variant: small-caps; margin-bottom: 1rem; font-size: 1.25rem; line-height: 1.75rem;' }, [ text(`Bonjour `), dom('span', { style: '' }, [ text(data.username) ]) ]),
|
||||
dom('p', { style: '' }, [ text(`Vous avez demandé à réinitialiser votre mot de passe aujourd'hui à ${ format(new Date(data.timestamp), 'HH:mm') }.`) ]),
|
||||
dom('div', { style: 'padding-top: 1rem; padding-bottom: 1rem; text-align: center;' }, [
|
||||
dom('a', { attributes: { href: `https://d-any.com/user/resetting-password?u=${data.userId}&i=${data.id}&t=${data.timestamp}&h=${hash}`, target: '_blank' } }, [ dom('span', { style: 'display: inline-block; border-width: 1px; border-color: #525252; background-color: #e5e5e5; padding-left: 0.75rem; padding-right: 0.75rem; padding-top: 0.25rem; padding-bottom: 0.25rem; font-weight: 200; color: #171717; text-decoration: none;' }, [ text('Je change mon mot de passe.') ]) ]),
|
||||
dom('span', { style: 'display: block; padding-top: 0.5rem; font-size: 0.75rem; line-height: 1rem;' }, [ text('Ce lien est valable 1 heure.') ])
|
||||
]),
|
||||
dom('div', { style: '' }, [
|
||||
dom('span', { style: '' }, [ text('Vous pouvez egalement copier le lien suivant pour valider votre compte: ') ]),
|
||||
dom('pre', { style: 'display: inline-block; border-bottom-width: 1px; font-size: 0.75rem; line-height: 1rem; color: #171717; font-weight: 400; text-decoration: none;' }, [ text(`https://d-any.com/user/mailvalidation?u=${data.userId}&i=${data.id}&t=${data.timestamp}&h=${hash}`) ])
|
||||
]),
|
||||
dom('span', { style: '', text: 'Si vous n\'êtes pas à l\'origine de cette demande, vous n\'avez pas à modifier votre mot de passe, ce dernier est conservé tant que vous n\'interagissez pas avec le lien ci-dessus.' }),
|
||||
])];
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<template>
|
||||
<div style="max-width: 800px; margin-left: auto; margin-right: auto;">
|
||||
<p style="font-variant: small-caps; margin-bottom: 1rem; font-size: 1.25rem; line-height: 1.75rem;">Bonjour <span>{{ username }}</span>.</p>
|
||||
<p>Vous avez demandé à réinitialiser votre mot de passe aujourd'hui à {{ format(new Date(timestamp), 'HH:mm') }}.</p>
|
||||
<div style="padding-top: 1rem; padding-bottom: 1rem; text-align: center;">
|
||||
<a :href="`https://d-any.com/user/resetting-password?u=${userId}&i=${id}&t=${timestamp}&h=${hash}`" target="_blank"><span style="display: inline-block; border-width: 1px; border-color: #525252; background-color: #e5e5e5; padding-left: 0.75rem; padding-right: 0.75rem; padding-top: 0.25rem; padding-bottom: 0.25rem; font-weight: 200; color: #171717; text-decoration: none;">Je change mon mot de passe.</span></a>
|
||||
<span style="display: block; padding-top: 0.5rem; font-size: 0.75rem; line-height: 1rem;">Ce lien est valable 1 heure.</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Vous pouvez egalement copier le lien suivant pour changer votre mot de passe: </span>
|
||||
<pre style="display: inline-block; border-bottom-width: 1px; font-size: 0.75rem; line-height: 1rem; color: #171717; font-weight: 400; text-decoration: none;">{{ `https://d-any.com/user/resetting-password?u=${userId}&i=${id}&t=${timestamp}&h=${hash}` }}</pre>
|
||||
</div>
|
||||
<span>Si vous n'êtes pas à l'origine de cette demande, vous n'avez pas à modifier votre mot de passe, ce dernier est conservé tant que vous n'interagissez pas avec le lien ci-dessus.</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import Bun from 'bun';
|
||||
import { format } from '#shared/general.util';
|
||||
|
||||
const { id, userId, username, timestamp } = defineProps<{
|
||||
id: number
|
||||
userId: number
|
||||
username: string
|
||||
timestamp: number
|
||||
}>();
|
||||
const hash = computed(() => Bun.hash('2' + userId.toString(), timestamp));
|
||||
</script>
|
||||
@@ -2,16 +2,20 @@ import nodemailer from 'nodemailer';
|
||||
import { createSSRApp, h } from 'vue';
|
||||
import { renderToString } from 'vue/server-renderer';
|
||||
|
||||
import base from '../components/mail/base.vue';
|
||||
import base from '../components/mail/base';
|
||||
import registration from '../components/mail/registration';
|
||||
import reset_password from '../components/mail/reset-password';
|
||||
|
||||
/* import base from '../components/mail/base.vue';
|
||||
import Registration from '../components/mail/registration.vue';
|
||||
import ResetPassword from '../components/mail/reset-password.vue';
|
||||
import ResetPassword from '../components/mail/reset-password.vue'; */
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
const [domain, selector, dkim] = config.mail.dkim.split(":");
|
||||
|
||||
export const templates: Record<string, { component: any, subject: string }> = {
|
||||
"registration": { component: Registration, subject: 'Bienvenue sur d[any] 😎' },
|
||||
"reset-password": { component: ResetPassword, subject: 'Réinitialisation de votre mot de passe' },
|
||||
export const templates: Record<string, { component: (data: any) => string[], subject: string }> = {
|
||||
"registration": { component: registration, subject: 'Bienvenue sur d[any] 😎' },
|
||||
"reset-password": { component: reset_password, subject: 'Réinitialisation de votre mot de passe' },
|
||||
};
|
||||
|
||||
import type Mail from 'nodemailer/lib/mailer';
|
||||
@@ -76,11 +80,13 @@ export default defineTask({
|
||||
throw new Error(`Modèle de mail ${mailPayload.template} inconnu`);
|
||||
}
|
||||
|
||||
console.log(`<html><body>${base(template.component(mailPayload.data))}</body></html>`);
|
||||
|
||||
console.time('Generating HTML');
|
||||
const mail: Mail.Options = {
|
||||
from: 'd[any] - Ne pas répondre <no-reply@peaceultime.com>',
|
||||
to: mailPayload.to,
|
||||
html: await render(template.component, mailPayload.data),
|
||||
html: `<html><body>${base(template.component(mailPayload.data))}</body></html>`,
|
||||
subject: template.subject,
|
||||
textEncoding: 'quoted-printable',
|
||||
};
|
||||
@@ -106,17 +112,4 @@ export default defineTask({
|
||||
return { result: false, error: e };
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
async function render(component: any, data: Record<string, any>): Promise<string>
|
||||
{
|
||||
const app = createSSRApp({
|
||||
render(){
|
||||
return h(base, null, { default: () => h(component, data, { default: () => null }) });
|
||||
}
|
||||
});
|
||||
|
||||
const html = await renderToString(app);
|
||||
|
||||
return (`<html><body><div>${html}</div></body></html>`);
|
||||
}
|
||||
})
|
||||
@@ -107,5 +107,5 @@ function _useSession(event: H3Event | CompatEvent) {
|
||||
|
||||
sessionConfig = runtimeConfig.session;
|
||||
}
|
||||
return useSession<UserSession>(event, sessionConfig);
|
||||
return useSession<UserSession>(event, sessionConfig ?? {});
|
||||
}
|
||||
Reference in New Issue
Block a user