Skip to content

Commit

Permalink
Merge pull request #171 from codeanker/feature/mjml
Browse files Browse the repository at this point in the history
implement mjml email templates
  • Loading branch information
danielswiatek authored Nov 7, 2024
2 parents 5636a48 + b4173b8 commit b4cd69b
Show file tree
Hide file tree
Showing 31 changed files with 1,703 additions and 83 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"source.fixAll.eslint": "explicit"
},
"editor.tabSize": 2,
"files.associations": {
"*.mjml": "html"
},
"files.trimTrailingWhitespace": true,
"files.trimFinalNewlines": true,
"files.insertFinalNewline": true,
Expand Down
6 changes: 6 additions & 0 deletions api/config/custom-environment-variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,11 @@
},
"tomtom": {
"apiKey": "TOMTOM_APIKEY"
},
"public": {
"legal": {
"imprint": "PUBLIC_LEGAL_IMPRINT",
"privacy": "PUBLIC_LEGAL_PRIVACY"
}
}
}
6 changes: 6 additions & 0 deletions api/config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,11 @@
},
"tomtom": {
"apiKey": ""
},
"public": {
"legal": {
"imprint": "",
"privacy": ""
}
}
}
73 changes: 73 additions & 0 deletions api/email/_layout.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<mjml>
<mj-head>
<mj-attributes>
<mj-all font-family="sans-serif" />
</mj-attributes>

<mj-style>
.footer {
padding: 10px 0;
}

.footer a,
.footer p {
color: #696969;
}
</mj-style>
</mj-head>

<mj-body background-color="#f1f5f9">
<mj-wrapper background-color="#fff" border-radius="32px">
<mj-section>
<mj-column vertical-align="middle">
<mj-text align="left" font-size="24px">{{ veranstaltung }}</mj-text>
</mj-column>
<mj-column vertical-align="middle">
<mj-text align="right" font-size="18px">DLRG {{ gliederung }}</mj-text>
</mj-column>
</mj-section>

<mj-section>
<mj-column>
<mj-text font-size="30px" font-weight="500">
{{ subject }}
</mj-text>

<mj-text font-size="16px">
Moin {{ name }},
</mj-text>

{{> @partial-block }}
</mj-column>
</mj-section>

<mj-section>
<mj-column>
<mj-text>
Viele Grüße
</mj-text>
<mj-text>
Dein Orga-Team
</mj-text>
</mj-column>
</mj-section>
</mj-wrapper>

<mj-section css-class="footer" padding="10px 0 0 0">
<mj-column>
<!-- Logo von LV -->
<mj-image width="192px" src="{{ url 'img/gliederung_sh.png' }}"></mj-image>
</mj-column>
</mj-section>

<mj-section css-class="footer" padding="0">
<mj-column>
<mj-text align="center" font-size="12px">
<a href="{{ config 'public.legal.imprint' }}">Impressum</a>
<span> - </span>
<a href="{{ config 'public.legal.privacy' }}">Datenschutz</a>
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
9 changes: 9 additions & 0 deletions api/email/account-activated.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{{#> layout }}

<mj-text font-size="16px" line-height="1.5">
Dein <b>{{ hostname }}</b> Account wurde bestätigt.
Bevor du dich anmelden kannst, muss dein Account noch durch einen Administrator
aktiviert werden.
</mj-text>

{{/layout}}
18 changes: 18 additions & 0 deletions api/email/account-email-confirm.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{{#> layout }}

<mj-text font-size="16px" line-height="1.5">
Dein <b>{{ hostname }}</b> Account wurde erstellt. Um den Registrierungsprozess
abzuschließen, bestätige deine E-Mail Adresse bitte mit dem nachfolgenden Link.
</mj-text>

<mj-button
align="left"
background-color="#16a34a"
border-radius="8px"
font-size="16px"
href="{{ activationUrl }}"
>
Account bestätigen
</mj-button>

{{/layout}}
18 changes: 18 additions & 0 deletions api/email/account-password-reset.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{{#> layout }}

<mj-text font-size="16px" line-height="1.5">
Wir haben eine Anfrage erhalten, das Passwort für deinen Account bei <b>{{ hostname }}</b> zurückzusetzen.
Nutze den nachfolgenden Link, um das zu tun.
</mj-text>

<mj-button
align="left"
background-color="#16a34a"
border-radius="8px"
font-size="16px"
href="{{ resetUrl }}"
>
Passwort zurücksetzen
</mj-button>

{{/layout}}
19 changes: 19 additions & 0 deletions api/email/account-status-changed.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{#> layout }}

<mj-text font-size="16px" line-height="1.5">
Der Status deines <b>{{ hostname }}</b> Account wurde auf <b>{{ status }}</b> geändert.
</mj-text>

{{#if isActive }}
<mj-button
align="left"
background-color="#16a34a"
border-radius="8px"
font-size="16px"
href="{{ config 'clientUrl' }}/login"
>
Zur Anmeldung
</mj-button>
{{/if}}

{{/layout}}
11 changes: 11 additions & 0 deletions api/email/registration-canceled.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{#> layout }}

<mj-text font-size="16px" line-height="1.5">
Deine Anmeldung zur Veranstaltung {{ veranstaltung }} <b>wurde storniert</b>.
</mj-text>

<mj-text font-size="16px" line-height="1.5">
Für Fragen wende dich bitte an deine Gliederung.
</mj-text>

{{/layout}}
11 changes: 11 additions & 0 deletions api/email/registration-confirmed.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{#> layout }}

<mj-text font-size="16px" line-height="1.5">
Deine Anmeldung zur Veranstaltung {{ veranstaltung }} <b>wurde bestätigt</b>.
</mj-text>

<mj-text font-size="16px" line-height="1.5">
Für Fragen wende dich bitte an deine Gliederung.
</mj-text>

{{/layout}}
11 changes: 11 additions & 0 deletions api/email/registration-rejected.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{{#> layout }}

<mj-text font-size="16px" line-height="1.5">
Deine Anmeldung zur Veranstaltung {{ veranstaltung }} <b>wurde abgelehnt</b>.
</mj-text>

<mj-text font-size="16px" line-height="1.5">
Bei Fragen wende dich bitte an deine Gliederung unter der nachfolgenden E-Mail Adresse:
</mj-text>

{{/layout}}
12 changes: 12 additions & 0 deletions api/email/registration-successful.mjml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{#> layout }}

<mj-text font-size="16px" line-height="1.5">
Vielen Dank für deine Anmeldung zur Veranstaltung {{ veranstaltung }}.
</mj-text>

<mj-text font-size="16px" line-height="1.5">
<b>Wichtig</b>: Deine Anmeldung ist noch nicht bestätigt. Sobald sich der Status
ändert, erhältst Du eine weitere E-Mail.
</mj-text>

{{/layout}}
4 changes: 4 additions & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,18 @@
"axios": "^1.7.7",
"config": "^3.3.9",
"dayjs": "^1.11.10",
"dot-prop": "^9.0.0",
"fast-csv": "^5.0.1",
"grant": "^5.4.22",
"handlebars": "^4.7.8",
"koa": "^2.14.2",
"koa-body": "^6.0.1",
"koa-helmet": "^7.0.2",
"koa-router": "^12.0.1",
"koa-session": "^6.4.0",
"koa-static": "^5.0.0",
"meilisearch": "^0.37.0",
"mjml": "^4.15.3",
"prom-client": "^15.0.0",
"superjson": "^2.2.1",
"trpc-koa-adapter": "^1.1.3",
Expand All @@ -60,6 +63,7 @@
"@types/koa": "^2.14.0",
"@types/koa-bodyparser": "^4.3.12",
"@types/koa-router": "^7.4.8",
"@types/mjml": "^4.7.4",
"@types/node": "^20.11.1",
"edge-runtime": "^2.5.8",
"prisma": "^5.19.1",
Expand Down
6 changes: 6 additions & 0 deletions api/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ export const configSchema = z.strictObject({
tomtom: z.strictObject({
apiKey: z.string(),
}),
public: z.strictObject({
legal: z.strictObject({
imprint: z.string().url(),
privacy: z.string().url(),
}),
}),
})

export default configSchema.parse(baseConfig)
5 changes: 4 additions & 1 deletion api/src/scripts/createAccount.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { input, password as passwordInput, select } from '@inquirer/prompts'
import { Role } from '@prisma/client'

import { getEnumOptions, roleMapping } from '../enumMappings'
import prisma from '../prisma'
Expand Down Expand Up @@ -31,14 +32,16 @@ async function createUser() {
})
}

const gliederungId = await selectGliederung()
const accountData = await getAccountCreateData({
email: email,
firstname: firstname,
lastname: lastname,
password: password,
roleId: roleId,
isActiv: true,
adminInGliederungId: roleId === 'GLIEDERUNG_ADMIN' ? await selectGliederung() : undefined,
gliederungId,
adminInGliederungId: roleId === Role.GLIEDERUNG_ADMIN ? gliederungId : undefined,
birthday: new Date(),
gender: 'FEMALE',
})
Expand Down
24 changes: 22 additions & 2 deletions api/src/services/account/accountActivate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ export const accountActivateProcedure = defineProcedure({
data: {
activatedAt: new Date(),
},
select: {
email: true,
person: {
select: {
firstname: true,
lastname: true,
gliederung: {
select: {
name: true,
},
},
},
},
},
})

await logActivity({
Expand All @@ -33,9 +47,15 @@ export const accountActivateProcedure = defineProcedure({

await sendMail({
to: account.email,
subject: 'brahmsee.digital Account aktiviert',
subject: 'Account aktiviert',
categories: ['account', 'activate'],
html: 'Dein brahmsee.digital Account wurde aktiviert.',
template: 'account-activated',
variables: {
gliederung: account.person.gliederung!.name,
name: `${account.person.firstname} ${account.person.lastname}`,
hostname: 'brahmsee.digital',
veranstaltung: 'brahmsee.digital',
},
})

return 'activated'
Expand Down
5 changes: 1 addition & 4 deletions api/src/services/account/accountEmailConfirmRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ export const accountEmailConfirmRequestProcedure = defineProcedure({
description: 'email confirmation requested',
})

await sendMailConfirmEmailRequest({
email: account.email,
activationToken: account.activationToken,
})
await sendMailConfirmEmailRequest(account.email, account.activationToken)

return {
success: true,
Expand Down
10 changes: 4 additions & 6 deletions api/src/services/account/accountGliederungAdminCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const ZAccountGliederungAdminCreateInput = z.strictObject({
birthday: z.date(),
email: z.string().email().optional(), // email is required, because oauth login does not have an email
password: z.string().optional(), // optional, because oauth login does not have a password
adminInGliederungId: z.number().int(),
gliederungId: z.number().int(),
jwtOAuthToken: z.string().optional(), // optional, becaus normal registration does not have a jwtOAuthToken
}),
})
Expand Down Expand Up @@ -57,7 +57,8 @@ export const accountGliederungAdminCreateProcedure = defineProcedure({
gender: options.input.data.gender,
roleId: 'GLIEDERUNG_ADMIN',
isActiv: false,
adminInGliederungId: options.input.data.adminInGliederungId,
gliederungId: options.input.data.gliederungId,
adminInGliederungId: options.input.data.gliederungId,
})
const res = await prisma.account.create({
data: {
Expand All @@ -69,10 +70,7 @@ export const accountGliederungAdminCreateProcedure = defineProcedure({
},
})

await sendMailConfirmEmailRequest({
email: accountData.email,
activationToken: accountData.activationToken,
})
await sendMailConfirmEmailRequest(accountData.email, accountData.activationToken!)

return res
},
Expand Down
Loading

0 comments on commit b4cd69b

Please sign in to comment.