diff --git a/config/scripts.yaml b/config/scripts.yaml index d26cbd7e176..4956aff14c0 100644 --- a/config/scripts.yaml +++ b/config/scripts.yaml @@ -61,7 +61,6 @@ backend: rmdb: 'node ./scripts/rmdb.mjs' test: 'npx mocha --require mocha-steps tests/index.mjs' vbuild: *vbuild - prebuild: &sitePrebuild 'node --conditions=internal --experimental-json-modules ./prebuild.mjs' dev: build: &nextBuild 'next build' @@ -71,7 +70,7 @@ dev: develop: *nextDev i18n: "SITE=dev node --conditions=internal ../shared/prebuild/i18n-only.mjs" lint: &nextLint 'next lint' - prebuild: *sitePrebuild + prebuild: &sitePrebuild 'node --conditions=internal --experimental-json-modules ./prebuild.mjs' serve: "pm2 start npm --name 'dev' -- run start" start: &nextStart 'yarn prebuild && yarn dev' diff --git a/markdown/org/docs/faq/newsletter/en.md b/markdown/org/docs/faq/newsletter/en.md new file mode 100644 index 00000000000..b7633e62566 --- /dev/null +++ b/markdown/org/docs/faq/newsletter/en.md @@ -0,0 +1,5 @@ +--- +title: Newsletter +--- + + diff --git a/markdown/org/docs/faq/newsletter/why-subscribe-multiple-clicks/en.md b/markdown/org/docs/faq/newsletter/why-subscribe-multiple-clicks/en.md new file mode 100644 index 00000000000..1c4e39e4f26 --- /dev/null +++ b/markdown/org/docs/faq/newsletter/why-subscribe-multiple-clicks/en.md @@ -0,0 +1,66 @@ +--- +title: Why do I have to click again to confirm I want to subscribe after I already clicked the confirmation link you sent me? +--- + +There are two aspects that cause signing up for our newsletter to require multiple clicks: + +- [People should only be able to sign up themselves](#people-should-only-be-able-to-sign-up-themselves) +- [GET requests should not make changes](#get-requests-should-not-make-changes) + +## People should only be able to sign up themselves + +This one is pretty easy to understand. One should not be able +to subscribe somebody else's email address to the FreeSewing newsletter. + +This is why, after indicating you want to sign up, we sent you a confirmation +email to the email address you provided. +If you receive this email, it confirms not only that the email address +is working, but also that you have access to it. + +In other words, only after you click the link in the confirmation email can we know for +cerntain that: + +- The email address is valid +- The owner of the email address wants to subscribe + +That's where it would be over. Except for one technical detail that's also important: + +## GET requests should not make changes + +This is more technical and harder to understand + +Another reason is that while we could make it so that clicking the link in your +email would immeadiatly subcribe you, it would be in violation of internet standards. +Specifically, the __HTTP__ protocol's __GET method__ definition which states that: + + + +
GET requests should only retrieve data and should have no other effect.
+ +[wikipedia.org/wiki/HTTP#HTTP/1.1_request_messages](https://en.wikipedia.org/wiki/HTTP#HTTP/1.1_request_messages) +
+ +A _GET request_ is what happens when you follow a link. Merely following a link +should not make any changes (like subscribing you to a newsletter). + +For example, when you receive an email, your email client +may _preload_ the links in it in the background. So that they are quicker to +load should you click on them. + +Obviously, this preloading should not confirm your subscription. Which is why +you need to click a button to confirm. Because that will trigger a __POST request__ +and those can make changes. + + + +##### This does not apply to users subscribing through their account + +None of this applies to users who subscribe to our newsletter by enabling the +option in our account. In this case, we do not need to go through the email +validation process, since we already did that when you signed up. + +For users, subscribing (and unsubscribing) is instant (If you are curious, +we use an idempotent __PUT request__ under the hood). + + + diff --git a/markdown/org/docs/faq/newsletter/why-unsubscribe-multiple-clicks/en.md b/markdown/org/docs/faq/newsletter/why-unsubscribe-multiple-clicks/en.md new file mode 100644 index 00000000000..1c4e39e4f26 --- /dev/null +++ b/markdown/org/docs/faq/newsletter/why-unsubscribe-multiple-clicks/en.md @@ -0,0 +1,66 @@ +--- +title: Why do I have to click again to confirm I want to subscribe after I already clicked the confirmation link you sent me? +--- + +There are two aspects that cause signing up for our newsletter to require multiple clicks: + +- [People should only be able to sign up themselves](#people-should-only-be-able-to-sign-up-themselves) +- [GET requests should not make changes](#get-requests-should-not-make-changes) + +## People should only be able to sign up themselves + +This one is pretty easy to understand. One should not be able +to subscribe somebody else's email address to the FreeSewing newsletter. + +This is why, after indicating you want to sign up, we sent you a confirmation +email to the email address you provided. +If you receive this email, it confirms not only that the email address +is working, but also that you have access to it. + +In other words, only after you click the link in the confirmation email can we know for +cerntain that: + +- The email address is valid +- The owner of the email address wants to subscribe + +That's where it would be over. Except for one technical detail that's also important: + +## GET requests should not make changes + +This is more technical and harder to understand + +Another reason is that while we could make it so that clicking the link in your +email would immeadiatly subcribe you, it would be in violation of internet standards. +Specifically, the __HTTP__ protocol's __GET method__ definition which states that: + + + +
GET requests should only retrieve data and should have no other effect.
+ +[wikipedia.org/wiki/HTTP#HTTP/1.1_request_messages](https://en.wikipedia.org/wiki/HTTP#HTTP/1.1_request_messages) +
+ +A _GET request_ is what happens when you follow a link. Merely following a link +should not make any changes (like subscribing you to a newsletter). + +For example, when you receive an email, your email client +may _preload_ the links in it in the background. So that they are quicker to +load should you click on them. + +Obviously, this preloading should not confirm your subscription. Which is why +you need to click a button to confirm. Because that will trigger a __POST request__ +and those can make changes. + + + +##### This does not apply to users subscribing through their account + +None of this applies to users who subscribe to our newsletter by enabling the +option in our account. In this case, we do not need to go through the email +validation process, since we already did that when you signed up. + +For users, subscribing (and unsubscribing) is instant (If you are curious, +we use an idempotent __PUT request__ under the hood). + + + diff --git a/sites/backend/package.json b/sites/backend/package.json index 42256a1c778..e516d8cec2b 100644 --- a/sites/backend/package.json +++ b/sites/backend/package.json @@ -24,9 +24,7 @@ "rmdb": "node ./scripts/rmdb.mjs", "test": "npx mocha --require mocha-steps tests/index.mjs", "vbuild": "VERBOSE=1 node build.mjs", - "prebuild": "node --conditions=internal --experimental-json-modules ./prebuild.mjs", - "wbuild": "node build.mjs", - "prewbuild": "node --conditions=internal --experimental-json-modules ./prebuild.mjs" + "wbuild": "node build.mjs" }, "peerDependencies": {}, "dependencies": { diff --git a/sites/backend/prebuild.mjs b/sites/backend/prebuild.mjs deleted file mode 100644 index bddd11c3d97..00000000000 --- a/sites/backend/prebuild.mjs +++ /dev/null @@ -1,14 +0,0 @@ -import { prebuildRunner } from '../shared/prebuild/runner.mjs' - -/* - * This handles the prebuild step for the FreeSewing backend - * It runs via an NPM run script, so in a pure NodeJS context - * - * See `sites/org/prebuild.mjs` for an example with inline comments - */ -prebuildRunner({ - site: 'backend', - prebuild: { - i18n: true, - }, -}) diff --git a/sites/backend/prisma/schema.prisma b/sites/backend/prisma/schema.prisma index 0881c6ebb5f..957bf9f39c6 100644 --- a/sites/backend/prisma/schema.prisma +++ b/sites/backend/prisma/schema.prisma @@ -30,10 +30,11 @@ model Confirmation { model Subscriber { id String @id @default(uuid()) + active Boolean @default(false) createdAt DateTime @default(now()) - data String ehash String @unique email String + language String @default("en") updatedAt DateTime @updatedAt } diff --git a/sites/backend/src/config.mjs b/sites/backend/src/config.mjs index 210d02b4bc5..7a9c7f692ac 100644 --- a/sites/backend/src/config.mjs +++ b/sites/backend/src/config.mjs @@ -35,6 +35,8 @@ const baseConfig = { env: process.env.NODE_ENV || 'development', // Maintainer contact maintainer: 'joost@freesewing.org', + // Backend API base URL + api: process.env.BACKEND_API_URL || 'https://backend3.freesewing.org', // Feature flags use: { github: envToBool(process.env.BACKEND_ENABLE_GITHUB), @@ -44,12 +46,12 @@ const baseConfig = { }, sanity: envToBool(process.env.BACKEND_ENABLE_SANITY), ses: envToBool(process.env.BACKEND_ENABLE_AWS_SES), - stripe: envToBool(process.env.BACKEND_ENABLE_PAYMENTS), tests: { base: envToBool(process.env.BACKEND_ENABLE_TESTS), email: envToBool(process.env.BACKEND_ENABLE_TESTS_EMAIL), sanity: envToBool(process.env.BACKEND_ENABLE_TESTS_SANITY), }, + import: envToBool(process.env.BACKEND_ENABLE_IMPORT), }, // Config api, @@ -86,7 +88,7 @@ const baseConfig = { audience: process.env.BACKEND_JWT_ISSUER || 'freesewing.org', expiresIn: process.env.BACKEND_JWT_EXPIRY || '7d', }, - languages: ['en', 'de', 'es', 'fr', 'nl'], + languages: ['en', 'de', 'es', 'fr', 'nl', 'uk'], translations: ['de', 'es', 'fr', 'nl', 'uk'], measies: measurements, mfa: { @@ -145,7 +147,7 @@ if (baseConfig.use.github) if (baseConfig.use.sanity) baseConfig.sanity = { project: process.env.SANITY_PROJECT, - dataset: process.env.SANITY_DATASET || 'production', + dataset: process.env.SANITY_DATASET || 'site-content', token: process.env.SANITY_TOKEN || 'fixmeSetSanityToken', version: process.env.SANITY_VERSION || 'v2022-10-31', api: `https://${process.env.SANITY_PROJECT || 'missing-project-id'}.api.sanity.io/${ @@ -153,14 +155,6 @@ if (baseConfig.use.sanity) }`, } -// Stripe config -if (baseConfig.use.stripe) - baseConfig.stripe = { - keys: { - createIntent: process.env.BACKEND_STRIPE_CREATE_INTENT_KEY || false, - }, - } - // AWS SES config (for sending out emails) if (baseConfig.use.ses) baseConfig.aws = { @@ -260,10 +254,6 @@ if (envToBool(process.env.BACKEND_ENABLE_OAUTH_GOOGLE)) { vars.BACKEND_OAUTH_GOOGLE_CLIENT_ID = 'required' vars.BACKEND_OAUTH_GOOGLE_CLIENT_SECRET = 'requiredSecret' } -// Vars for Stripe integration -if (envToBool(process.env.BACKEND_ENABLE_PAYMENTS)) { - vars.BACKEND_STRIPE_CREATE_INTENT_KEY = 'requiredSecret' -} // Vars for (unit) tests if (envToBool(process.env.BACKEND_ENABLE_TESTS)) { @@ -339,11 +329,6 @@ export function verifyConfig(silent = false) { config.jwt.secretOrKey.slice(0, 4) + '**redacted**' + config.jwt.secretOrKey.slice(-4), }, } - if (config.stripe) - dump.stripe = { - ...config.stripe.keys, - //token: config.sanity.token.slice(0, 4) + '**redacted**' + config.sanity.token.slice(-4), - } if (config.sanity) dump.sanity = { ...config.sanity, diff --git a/sites/backend/src/controllers/imports.mjs b/sites/backend/src/controllers/imports.mjs new file mode 100644 index 00000000000..958e2cdea4b --- /dev/null +++ b/sites/backend/src/controllers/imports.mjs @@ -0,0 +1,18 @@ +import { ImportModel } from '../models/import.mjs' + +export function ImportsController() {} + +/* + * Imports newsletters subscribers in v2 format + */ +ImportsController.prototype.subscribers = async (req, res, tools) => { + /* + * This is a special route that uses hard-coded credentials + */ + console.log(req.body) + + const Import = new ImportModel(tools) + //await Flow.sendTranslatorInvite(req) + + return Import.sendResponse(res) +} diff --git a/sites/backend/src/controllers/payments.mjs b/sites/backend/src/controllers/payments.mjs deleted file mode 100644 index 08e5543de9f..00000000000 --- a/sites/backend/src/controllers/payments.mjs +++ /dev/null @@ -1,34 +0,0 @@ -export function PaymentsController() {} - -/* - * Create payment intent - * - * This is the endpoint that handles creation of a Stripe payment intent - * See: https://freesewing.dev/reference/backend/api/apikey - */ -PaymentsController.prototype.createIntent = async (req, res, tools) => { - if (!req.body.amount) return this.setResponse(400, 'amountMissing') - if (!req.body.currency) return this.setResponse(400, 'currencyMissing') - - const body = new URLSearchParams() - body.append('amount', req.body.amount) - body.append('currency', req.body.currency) - - // Call Stripe API with fetch to create the payment inent - const result = await fetch('https://api.stripe.com/v1/payment_intents', { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', - authorization: `Bearer ${tools.config.stripe.keys.createIntent}`, - }, - body, - }) - // Convert response to JSON - const json = await result.json() - - // Return status code 201 (created) and clientSecret - return res.status(201).send({ - result: 'success', - clientSecret: json.client_secret, - }) -} diff --git a/sites/backend/src/controllers/subscribers.mjs b/sites/backend/src/controllers/subscribers.mjs new file mode 100644 index 00000000000..3fe58934314 --- /dev/null +++ b/sites/backend/src/controllers/subscribers.mjs @@ -0,0 +1,68 @@ +//import fs from 'fs' +//import path from 'path' +import { SubscriberModel } from '../models/subscriber.mjs' + +/* + * Load pages for subscribe and unsubscribe confirmation + * Some people might find this extra step annoying, + * but GET requests should not make changes. + */ +//const index = fs.readFileSync(path.resolve('.', 'src', 'landing', 'index.html')) +//app.get('/', async (req, res) => res.set('Content-Type', 'text/html').status(200).send(index)) + +export function SubscribersController() {} + +/* + * Subscribe to the newsletter (sends confirmation email) + * See: https://freesewing.dev/reference/backend/api + */ +SubscribersController.prototype.subscribe = async (req, res, tools) => { + const Subscriber = new SubscriberModel(tools) + await Subscriber.guardedCreate(req) + + return Subscriber.sendResponse(res) +} + +/* + * Subscribe confirmation + * See: https://freesewing.dev/reference/backend/api + */ +SubscribersController.prototype.subscribeConfirm = async (req, res, tools) => { + const Subscriber = new SubscriberModel(tools) + await Subscriber.subscribeConfirm(req) + + return Subscriber.sendResponse(res) +} + +/* + * Unsubscribe confirmation + * See: https://freesewing.dev/reference/backend/api + */ +SubscribersController.prototype.unsubscribeConfirm = async (req, res, tools) => { + const Subscriber = new SubscriberModel(tools) + await Subscriber.unsubscribeConfirm(req) + + return Subscriber.sendResponse(res) +} + +/* + * Confirm newsletter subscription + * See: https://freesewing.dev/reference/backend/api + */ +SubscribersController.prototype.confirm = async (req, res, tools) => { + const Subscriber = new SubscriberModel(tools) + await Subscriber.confirm(req) + + return Subscriber.sendResponse(res) +} + +/* + * Unsubscribe from the newsletter + * See: https://freesewing.dev/reference/backend/api + */ +SubscribersController.unsubscribe = async (req, res, tools) => { + const Subscriber = new SubscriberModel(tools) + await Subscriber.unsubscribe(req) + + return Subscriber.sendResponse(res) +} diff --git a/sites/backend/src/html/catch-all.mjs b/sites/backend/src/html/catch-all.mjs new file mode 100644 index 00000000000..36763defaf8 --- /dev/null +++ b/sites/backend/src/html/catch-all.mjs @@ -0,0 +1,18 @@ +import { wrapper } from './shared.mjs' + +export const html = wrapper({ + content: ` +

👋

+

This is the FreeSewing backend

+

+ For info about FreeSewing, try freesewing.org instead. +

+

+ For info about this backend, refer to the FreeSewing backend refefence documentation. +

+

+ For questions, join us at + discord.freesewing.org +

+`, +}) diff --git a/sites/backend/src/html/shared.mjs b/sites/backend/src/html/shared.mjs new file mode 100644 index 00000000000..ccb7701d133 --- /dev/null +++ b/sites/backend/src/html/shared.mjs @@ -0,0 +1,16 @@ +export const wrapper = ({ title = 'FreeSewing', header, content, footer }) => ` + + + + + ${title} + + + +
+ ${header ? header : ''} +
${content}
+ +
+ +` diff --git a/sites/backend/src/index.mjs b/sites/backend/src/index.mjs index 207a91f3b75..fb1d490db56 100644 --- a/sites/backend/src/index.mjs +++ b/sites/backend/src/index.mjs @@ -1,8 +1,6 @@ // Dependencies import express from 'express' import chalk from 'chalk' -import path from 'path' -import fs from 'fs' import { PrismaClient } from '@prisma/client' import passport from 'passport' // Routes @@ -22,6 +20,8 @@ import { mailer } from './utils/email.mjs' // Swagger import swaggerUi from 'swagger-ui-express' import { openapi } from '../openapi/index.mjs' +// Catch-all page +import { html as catchAll } from './html/catch-all.mjs' // Bootstrap const config = verifyConfig() @@ -49,9 +49,7 @@ loadPassportMiddleware(passport, tools) // Load routes for (const type in routes) routes[type](tools) -// Catch-all route (Load index.html once instead of at every request) -const index = fs.readFileSync(path.resolve('.', 'src', 'landing', 'index.html')) -app.get('/', async (req, res) => res.set('Content-Type', 'text/html').status(200).send(index)) +app.get('/', async (req, res) => res.set('Content-Type', 'text/html').status(200).send(catchAll)) // Start listening for requests app.listen(config.port, (err) => { diff --git a/sites/backend/src/landing/index.html b/sites/backend/src/landing/index.html deleted file mode 100644 index e64c9568c02..00000000000 --- a/sites/backend/src/landing/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - FreeSewing backend - - - -
- -
-

👋

-

This is the FreeSewing backend

-

- For info about FreeSewing, try freesewing.org instead. -

-

- For info about this backend, refer to the FreeSewing backend refefence documentation. -

-

- For questions, join us at - discord.freesewing.org -

-
- -
- - diff --git a/sites/backend/src/landing/invalid.html b/sites/backend/src/landing/invalid.html deleted file mode 100644 index 47058631900..00000000000 --- a/sites/backend/src/landing/invalid.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - Your request is invalid - - - - -
-

What are you doing?

-

Try freesewing.org instead.

-
- - - diff --git a/sites/backend/src/models/subscriber.mjs b/sites/backend/src/models/subscriber.mjs new file mode 100644 index 00000000000..1600c694596 --- /dev/null +++ b/sites/backend/src/models/subscriber.mjs @@ -0,0 +1,297 @@ +import { hash, randomString } from '../utils/crypto.mjs' +import { setUserAvatar } from '../utils/sanity.mjs' +import { log } from '../utils/log.mjs' +import { clean, i18nUrl } from '../utils/index.mjs' + +export function SubscriberModel(tools) { + this.config = tools.config + this.prisma = tools.prisma + this.mailer = tools.email + this.decrypt = tools.decrypt + this.encrypt = tools.encrypt + this.encryptedFields = ['email'] + this.clear = {} // For holding decrypted data + + return this +} + +SubscriberModel.prototype.guardedCreate = async function ({ body }) { + if (!body.email || typeof body.email !== 'string') return this.setResponse(400, 'emailMissing') + if (!body.language || !this.config.languages.includes(body.language.toLowerCase())) + return this.setResponse(400, 'languageMissing') + + // Clean up email address and hash it + const email = clean(body.email) + const language = body.language.toLowerCase() + const ehash = hash(email) + + log.info(`New newsletter subscriber: ${email}`) + + // Check whether this is a unit test + const isTest = this.isTest(body) + + // Check to see if this email address is already subscribed. + let newSubscriber = false + await this.read({ ehash }) + + if (!this.record) { + // No record found. Create subscriber record. + newSubscriber = true + const data = await this.cloak({ ehash, email, language, active: false }) + try { + this.record = await this.prisma.subscriber.create({ data }) + } catch (err) { + log.warn(err, 'Could not create subscriber record') + return this.setResponse(500, 'createSubscriberFailed') + } + } + + // Construct the various URLs + const actionUrl = i18nUrl( + `/newsletter/${this.record.active ? 'un' : ''}subscribe/${this.record.id}/${ehash}` + ) + + // Send out confirmation email unless it's a test and we don't want to send test emails + if (!isTest || this.config.use.tests.email) { + const template = newSubscriber ? 'nlsub' : this.record.active ? 'nlsubact' : 'nlsubinact' + + await this.mailer.send({ + template, + language, + to: email, + replacements: { + actionUrl, + whyUrl: i18nUrl(body.language, `/docs/faq/email/why-${template}`), + supportUrl: i18nUrl(body.language, `/patrons/join`), + }, + }) + } + + const returnData = { language, email } + if (isTest) { + returnData.id = this.record.id + returnData.ehash = ehash + } + + return this.setResponse(200, 'success', { data: returnData }) +} + +SubscriberModel.prototype.subscribeConfirm = async function ({ body }) { + const { id, ehash } = body + if (!id) return this.setResponse(400, 'idMissing') + if (!ehash) return this.setResponse(400, 'ehashMissing') + + // Find subscription + await this.read({ ehash }) + + if (!this.record) { + // Subscriber not found + return this.setResponse(404, 'subscriberNotFound') + } + + if (this.record.status !== true) { + // Update username + try { + await this.unguardedUpdate({ active: true }) + } catch (err) { + log.warn(err, 'Could not update active state after subscribe confirmation') + return this.setResponse(500, 'subscriberActivationFailed') + } + } + + return this.setResponse(200, 'success') +} + +SubscriberModel.prototype.unsubscribeConfirm = async function ({ body }) { + const { id, ehash } = body + if (!id) return this.setResponse(400, 'idMissing') + if (!ehash) return this.setResponse(400, 'ehashMissing') + + // Find subscription + await this.read({ ehash }) + + if (this.record) { + // Remove record + try { + await this.unguardedDelete() + } catch (err) { + log.warn(err, 'Could not remove subscriber') + return this.setResponse(500, 'subscriberRemovalFailed') + } + } + + return this.setResponse(200, 'success') +} + +/* + * Updates the subscriber data + * Used when we create the data ourselves so we know it's safe + */ +SubscriberModel.prototype.unguardedUpdate = async function (data) { + try { + this.record = await this.prisma.subscriber.update({ + where: { id: this.record.id }, + data, + }) + } catch (err) { + log.warn(err, 'Could not update subscriber record') + process.exit() + return this.setResponse(500, 'updateSubscriberFailed') + } + await this.reveal() + + return this.setResponse(200) +} + +/* + * Removes the subscriber record + * Used when we call for removal ourselves so we know it's safe + */ +SubscriberModel.prototype.unguardedDelete = async function () { + await this.prisma.subscriber.delete({ where: { id: this.record.id } }) + this.record = null + this.clear = null + + return this.subscriberExists() +} + +/* + * Loads a subscriber from the database based on the where clause you pass it + * + * Stores result in this.record + */ +SubscriberModel.prototype.read = async function (where) { + try { + this.record = await this.prisma.subscriber.findUnique({ where }) + } catch (err) { + log.warn({ err, where }, 'Could not read subscriber') + } + + this.reveal() + + return this.subscriberExists() +} + +/* + * Checks this.record and sets a boolean to indicate whether + * the subscription exists or not + * + * Stores result in this.exists + */ +SubscriberModel.prototype.subscriberExists = function () { + this.exists = this.record ? true : false + + return this +} + +/* + * Loads a measurements set from the database based on the where clause you pass it + * In addition prepares it for returning the set data + * + * Stores result in this.record + */ +SubscriberModel.prototype.guardedRead = async function ({ params, user }) { + if (!this.rbac.readSome(user)) return this.setResponse(403, 'insufficientAccessLevel') + if (user.iss && user.status < 1) return this.setResponse(403, 'accountStatusLacking') + + await this.read({ id: parseInt(params.id) }) + if (!this.record) return this.setResponse(404) + if (this.record.userId !== user.uid && !this.rbac.bughunter(user)) { + return this.setResponse(403, 'insufficientAccessLevel') + } + + return this.setResponse(200, false, { + result: 'success', + set: this.asSet(), + }) +} + +/* + * Helper method to decrypt at-rest data + */ +SubscriberModel.prototype.reveal = async function () { + this.clear = {} + if (this.record) { + for (const field of this.encryptedFields) { + try { + this.clear[field] = this.decrypt(this.record[field]) + } catch (err) { + console.log(err) + } + } + } + + return this +} + +/* + * Helper method to encrypt at-rest data + */ +SubscriberModel.prototype.cloak = function (data) { + for (const field of this.encryptedFields) { + if (typeof data[field] !== 'undefined') { + data[field] = this.encrypt(data[field]) + } + } + + return data +} + +/* + * Removes the subscriber - No questions asked + */ +SubscriberModel.prototype.unguardedDelete = async function () { + await this.prisma.subscriber.delete({ where: { id: this.record.id } }) + this.record = null + this.clear = null + + return this.subscriberExists() +} + +/* + * Helper method to set the response code, result, and body + * + * Will be used by this.sendResponse() + */ +SubscriberModel.prototype.setResponse = function ( + status = 200, + error = false, + data = {}, + rawData = false +) { + this.response = { + status, + body: rawData + ? data + : { + result: 'success', + ...data, + }, + } + if (status > 201) { + this.response.body.error = error + this.response.body.result = 'error' + this.error = true + } else this.error = false + + return this.subscriberExists() +} + +/* + * Helper method to send response (as JSON) + */ +SubscriberModel.prototype.sendResponse = async function (res) { + return res.status(this.response.status).send(this.response.body) +} + +/* + * Update method to determine whether this request is part of a (unit) test + */ +SubscriberModel.prototype.isTest = function (body) { + // Disalowing tests in prodution is hard-coded to protect people from themselves + if (this.config.env === 'production' && !this.config.tests.production) return false + if (!body.test) return false + if (body.email && !body.email.split('@').pop() === this.config.tests.domain) return false + + return true +} diff --git a/sites/backend/src/routes/import.mjs b/sites/backend/src/routes/import.mjs new file mode 100644 index 00000000000..ea8a23d9980 --- /dev/null +++ b/sites/backend/src/routes/import.mjs @@ -0,0 +1,14 @@ +import { ImportController } from '../controllers/import.mjs' + +const Import = new ImportController() + +export function importsRoutes(tools) { + const { app } = tools + + /* + * All these routes use hard-coded credentials because they should never be used + * outside the v2-v3 migration which is handled by joost + */ + // Import newsletter subscriptions + app.post('/import/subscribers', (req, res) => Import.subscribers(req, res, tools)) +} diff --git a/sites/backend/src/routes/index.mjs b/sites/backend/src/routes/index.mjs index d15916f33cb..83d6ebe8df9 100644 --- a/sites/backend/src/routes/index.mjs +++ b/sites/backend/src/routes/index.mjs @@ -5,8 +5,8 @@ import { patternsRoutes } from './patterns.mjs' import { confirmationsRoutes } from './confirmations.mjs' import { curatedSetsRoutes } from './curated-sets.mjs' import { issuesRoutes } from './issues.mjs' +import { subscribersRoutes } from './subscribers.mjs' import { flowsRoutes } from './flows.mjs' -import { paymentsRoutes } from './payments.mjs' export const routes = { apikeysRoutes, @@ -16,6 +16,6 @@ export const routes = { confirmationsRoutes, curatedSetsRoutes, issuesRoutes, + subscribersRoutes, flowsRoutes, - paymentsRoutes, } diff --git a/sites/backend/src/routes/payments.mjs b/sites/backend/src/routes/payments.mjs deleted file mode 100644 index 9be9e76d466..00000000000 --- a/sites/backend/src/routes/payments.mjs +++ /dev/null @@ -1,15 +0,0 @@ -import { PaymentsController } from '../controllers/payments.mjs' - -const Payments = new PaymentsController() - -export function paymentsRoutes(tools) { - const { app } = tools - - /* - * Only add these routes if payments are enabled in the config - */ - if (tools.config.use.stripe) { - // Create payment intent - app.post('/payments/intent', (req, res) => Payments.createIntent(req, res, tools)) - } -} diff --git a/sites/backend/src/routes/subscribers.mjs b/sites/backend/src/routes/subscribers.mjs new file mode 100644 index 00000000000..acebf75f222 --- /dev/null +++ b/sites/backend/src/routes/subscribers.mjs @@ -0,0 +1,20 @@ +import { SubscribersController } from '../controllers/subscribers.mjs' + +const Subscriber = new SubscribersController() + +export function subscribersRoutes(tools) { + const { app } = tools + + /* + * None of these require authentication + */ + + // Subscribe to the newsletter + app.post('/subscriber', (req, res) => Subscriber.subscribe(req, res, tools)) + + // Confirm subscription to the newsletter + app.put('/subscriber', (req, res) => Subscriber.subscribeConfirm(req, res, tools)) + + // Unsubscribe from newsletter + app.delete('/subscriber', (req, res) => Subscriber.unsubscribeConfirm(req, res, tools)) +} diff --git a/sites/backend/src/templates/email/de.json b/sites/backend/src/templates/email/de.json new file mode 100644 index 00000000000..4a1d0374546 --- /dev/null +++ b/sites/backend/src/templates/email/de.json @@ -0,0 +1,10 @@ +{ + "greeting": "Ganz liebe Grüße", + "ps-pre-link": "FreeSewing ist kostenlos (duh), aber bitte", + "ps-link": "werde ein/e Förderer/-in", + "ps-post-link": "wenn du es dir leisten kannst.", + "text-ps": "FreeSewing ist kostenlos, aber wenn du es dir leisten kannst, werde bitte Förderer/-in.", + "notMarketing": "Dies ist keine Marketing-E-Mail, sondern eine Transaktions-E-Mail über dein FreeSewing-Konto.", + "seeWhy": "Weitere Informationen findest du hier:", + "whyDidIGetThis": "Warum habe ich diese E-Mail bekommen?" +} diff --git a/sites/backend/src/templates/email/de.yaml b/sites/backend/src/templates/email/de.yaml deleted file mode 100644 index e6477d84f14..00000000000 --- a/sites/backend/src/templates/email/de.yaml +++ /dev/null @@ -1,9 +0,0 @@ -#Shared -greeting: Ganz liebe Grüße -ps-pre-link: FreeSewing ist kostenlos (duh), aber bitte -ps-link: werde ein/e Förderer/-in -ps-post-link: wenn du es dir leisten kannst. -text-ps: 'FreeSewing ist kostenlos, aber wenn du es dir leisten kannst, werde bitte Förderer/-in.' -notMarketing: Dies ist keine Marketing-E-Mail, sondern eine Transaktions-E-Mail über dein FreeSewing-Konto. -seeWhy: 'Weitere Informationen findest du hier:' -whyDidIGetThis: Warum habe ich diese E-Mail bekommen? diff --git a/sites/backend/src/templates/email/emailchange/de.json b/sites/backend/src/templates/email/emailchange/de.json new file mode 100644 index 00000000000..40e45c32807 --- /dev/null +++ b/sites/backend/src/templates/email/emailchange/de.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Bestätige deine neue E-Mail-Adresse", + "heading": "Funktioniert diese neue E-Mail-Adresse?", + "lead": "Um deine neue E-Mail-Adresse zu bestätigen, klicke auf das große schwarze Rechteck unten:", + "text-lead": "Um deine neue E-Mail-Adresse zu bestätigen, klicke auf den Link unten:", + "button": "Bestätige die E-Mail-Änderung", + "closing": "Mehr muss nicht getan werden." +} diff --git a/sites/backend/src/templates/email/emailchange/de.yaml b/sites/backend/src/templates/email/emailchange/de.yaml deleted file mode 100644 index cce9ca391bf..00000000000 --- a/sites/backend/src/templates/email/emailchange/de.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Bestätige deine neue E-Mail-Adresse" -heading: Funktioniert diese neue E-Mail-Adresse? -lead: 'Um deine neue E-Mail-Adresse zu bestätigen, klicke auf das große schwarze Rechteck unten:' -text-lead: 'Um deine neue E-Mail-Adresse zu bestätigen, klicke auf den Link unten:' -button: Bestätige die E-Mail-Änderung -closing: Mehr muss nicht getan werden. diff --git a/sites/backend/src/templates/email/emailchange/en.json b/sites/backend/src/templates/email/emailchange/en.json new file mode 100644 index 00000000000..8b644a8dfce --- /dev/null +++ b/sites/backend/src/templates/email/emailchange/en.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Confirm your new E-mail address", + "heading": "Does this new E-mail address work?", + "lead": "To confirm your new E-mail address, click the big black rectangle below:", + "text-lead": "To confirm your new E-mail address, click the link below:", + "button": "Confirm E-mail change", + "closing": "That's all it takes." +} diff --git a/sites/backend/src/templates/email/emailchange/en.yaml b/sites/backend/src/templates/email/emailchange/en.yaml deleted file mode 100644 index 5d9931e6140..00000000000 --- a/sites/backend/src/templates/email/emailchange/en.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Confirm your new E-mail address" -heading: Does this new E-mail address work? -lead: 'To confirm your new E-mail address, click the big black rectangle below:' -text-lead: 'To confirm your new E-mail address, click the link below:' -button: Confirm E-mail change -closing: That's all it takes. diff --git a/sites/backend/src/templates/email/emailchange/es.json b/sites/backend/src/templates/email/emailchange/es.json new file mode 100644 index 00000000000..728960101c9 --- /dev/null +++ b/sites/backend/src/templates/email/emailchange/es.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Confirma tu nueva dirección de correo electrónico", + "heading": "¿Funciona esta nueva dirección de correo electrónico?", + "lead": "Para confirmar tu nueva dirección de correo electrónico, haz clic en el rectángulo negro grande de abajo:", + "text-lead": "Para confirmar tu nueva dirección de correo electrónico, haz clic en el siguiente enlace:", + "button": "Confirmar cambio de e-mail", + "closing": "Eso es todo lo que hace falta." +} diff --git a/sites/backend/src/templates/email/emailchange/es.yaml b/sites/backend/src/templates/email/emailchange/es.yaml deleted file mode 100644 index 5655e133f65..00000000000 --- a/sites/backend/src/templates/email/emailchange/es.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Confirma tu nueva dirección de correo electrónico" -heading: '¿Funciona esta nueva dirección de correo electrónico?' -lead: 'Para confirmar tu nueva dirección de correo electrónico, haz clic en el rectángulo negro grande de abajo:' -text-lead: 'Para confirmar tu nueva dirección de correo electrónico, haz clic en el siguiente enlace:' -button: Confirmar cambio de e-mail -closing: Eso es todo lo que hace falta. diff --git a/sites/backend/src/templates/email/emailchange/fr.json b/sites/backend/src/templates/email/emailchange/fr.json new file mode 100644 index 00000000000..3cb5f29b16c --- /dev/null +++ b/sites/backend/src/templates/email/emailchange/fr.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Confirme ta nouvelle adresse e-mail", + "heading": "Cette nouvelle adresse électronique fonctionne-t-elle ?", + "lead": "Pour confirmer ta nouvelle adresse e-mail, clique sur le grand rectangle noir ci-dessous :", + "text-lead": "Pour confirmer ta nouvelle adresse e-mail, clique sur le lien ci-dessous :", + "button": "Confirmer le changement d'e-mail", + "closing": "C'est tout ce qu'il faut." +} diff --git a/sites/backend/src/templates/email/emailchange/fr.yaml b/sites/backend/src/templates/email/emailchange/fr.yaml deleted file mode 100644 index e0379d2965d..00000000000 --- a/sites/backend/src/templates/email/emailchange/fr.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Confirme ta nouvelle adresse e-mail" -heading: Cette nouvelle adresse électronique fonctionne-t-elle ? -lead: 'Pour confirmer ta nouvelle adresse e-mail, clique sur le grand rectangle noir ci-dessous :' -text-lead: 'Pour confirmer ta nouvelle adresse e-mail, clique sur le lien ci-dessous :' -button: Confirmer le changement d'e-mail -closing: C'est tout ce qu'il faut. diff --git a/sites/backend/src/templates/email/emailchange/index.mjs b/sites/backend/src/templates/email/emailchange/index.mjs index 5ccc98d311f..a90fa9197a6 100644 --- a/sites/backend/src/templates/email/emailchange/index.mjs +++ b/sites/backend/src/templates/email/emailchange/index.mjs @@ -1,10 +1,11 @@ import { buttonRow, closingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs' // Translations -import en from '../../../../public/locales/en/emailchange.json' assert { type: 'json' } -import de from '../../../../public/locales/de/emailchange.json' assert { type: 'json' } -import es from '../../../../public/locales/es/emailchange.json' assert { type: 'json' } -import fr from '../../../../public/locales/fr/emailchange.json' assert { type: 'json' } -import nl from '../../../../public/locales/nl/emailchange.json' assert { type: 'json' } +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } export const emailchange = { html: wrap.html(` @@ -16,4 +17,4 @@ export const emailchange = { text: wrap.text(`${headingRow.text}${lead1Row.text}${buttonRow.text}${closingRow.text}`), } -export const translations = { en, de, es, fr, nl } +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/emailchange/nl.json b/sites/backend/src/templates/email/emailchange/nl.json new file mode 100644 index 00000000000..ec0fb3595c2 --- /dev/null +++ b/sites/backend/src/templates/email/emailchange/nl.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Bevestig je nieuwe e-mailadres", + "heading": "Werkt dit nieuwe e-mailadres?", + "lead": "Klik op de grote zwarte rechthoek hieronder om je nieuwe e-mailadres te bevestigen:", + "text-lead": "Klik op de link hieronder om je nieuwe e-mailadres te bevestigen:", + "button": "E-mailwijziging bevestigen", + "closing": "Langer hoeft dat niet te duren." +} diff --git a/sites/backend/src/templates/email/emailchange/nl.yaml b/sites/backend/src/templates/email/emailchange/nl.yaml deleted file mode 100644 index 6171b03c149..00000000000 --- a/sites/backend/src/templates/email/emailchange/nl.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Bevestig je nieuwe e-mailadres" -heading: Werkt dit nieuwe e-mailadres? -lead: 'Klik op de grote zwarte rechthoek hieronder om je nieuwe e-mailadres te bevestigen:' -text-lead: 'Klik op de link hieronder om je nieuwe e-mailadres te bevestigen:' -button: E-mailwijziging bevestigen -closing: Langer hoeft dat niet te duren. diff --git a/sites/backend/src/templates/email/emailchange/uk.json b/sites/backend/src/templates/email/emailchange/uk.json new file mode 100644 index 00000000000..833c9bcd764 --- /dev/null +++ b/sites/backend/src/templates/email/emailchange/uk.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Підтвердіть свою нову електронну адресу", + "heading": "Чи працює ця нова електронна адреса?", + "lead": "Щоб підтвердити свою нову електронну адресу, натисніть на великий чорний прямокутник нижче:", + "text-lead": "Щоб підтвердити свою нову електронну адресу, перейдіть за посиланням нижче:", + "button": "Підтвердити зміну електронної пошти", + "closing": "Це все, що потрібно." +} diff --git a/sites/backend/src/templates/email/emailchange/uk.yaml b/sites/backend/src/templates/email/emailchange/uk.yaml deleted file mode 100644 index 89e4a1ec6b8..00000000000 --- a/sites/backend/src/templates/email/emailchange/uk.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Підтвердіть свою нову електронну адресу" -heading: Чи працює ця нова електронна адреса? -lead: 'Щоб підтвердити свою нову електронну адресу, натисніть на великий чорний прямокутник нижче:' -text-lead: 'Щоб підтвердити свою нову електронну адресу, перейдіть за посиланням нижче:' -button: Підтвердити зміну електронної пошти -closing: Це все, що потрібно. diff --git a/sites/backend/src/templates/email/en.json b/sites/backend/src/templates/email/en.json new file mode 100644 index 00000000000..09d2417ee14 --- /dev/null +++ b/sites/backend/src/templates/email/en.json @@ -0,0 +1,10 @@ +{ + "greeting": "love", + "ps-pre-link": "FreeSewing is free (duh), but please", + "ps-link": "become a patron", + "ps-post-link": "if you can afford it.", + "text-ps": "FreeSewing is free (duh), but please become a patron if you can afford it.", + "notMarketing": "This is not marketing, but a transactional email about your FreeSewing account.", + "seeWhy": "For more info, see:", + "whyDidIGetThis": "Why did I get this email?" +} diff --git a/sites/backend/src/templates/email/en.yaml b/sites/backend/src/templates/email/en.yaml deleted file mode 100644 index e20a59187dd..00000000000 --- a/sites/backend/src/templates/email/en.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# Shared -greeting: love -ps-pre-link: FreeSewing is free (duh), but please -ps-link: become a patron -ps-post-link: if you can afford it. -text-ps: 'FreeSewing is free (duh), but please become a patron if you can afford it.' -notMarketing: This is not marketing, but a transactional email about your FreeSewing account. -seeWhy: 'For more info, see:' -whyDidIGetThis: Why did I get this email? diff --git a/sites/backend/src/templates/email/es.json b/sites/backend/src/templates/email/es.json new file mode 100644 index 00000000000..7ecbd4056e6 --- /dev/null +++ b/sites/backend/src/templates/email/es.json @@ -0,0 +1,10 @@ +{ + "greeting": "con amor", + "ps-pre-link": "FreeSewing es gratis (duh), pero por favor", + "ps-link": "conviértete en un mecenas", + "ps-post-link": "si te lo puedes permitir.", + "text-ps": "FreeSewing es gratis (duh), pero hazte mecenas si puedes permitírtelo.", + "notMarketing": "No se trata de marketing, sino de un correo electrónico transaccional sobre tu cuenta de FreeSewing.", + "seeWhy": "Para más información, consulta:", + "whyDidIGetThis": "¿Por qué he recibido este correo electrónico?" +} diff --git a/sites/backend/src/templates/email/es.yaml b/sites/backend/src/templates/email/es.yaml deleted file mode 100644 index b6e787224a9..00000000000 --- a/sites/backend/src/templates/email/es.yaml +++ /dev/null @@ -1,9 +0,0 @@ -#Shared -greeting: con amor -ps-pre-link: FreeSewing es gratis (duh), pero por favor -ps-link: conviértete en un mecenas -ps-post-link: si te lo puedes permitir. -text-ps: 'FreeSewing es gratis (duh), pero hazte mecenas si puedes permitírtelo.' -notMarketing: No se trata de marketing, sino de un correo electrónico transaccional sobre tu cuenta de FreeSewing. -seeWhy: 'Para más información, consulta:' -whyDidIGetThis: '¿Por qué he recibido este correo electrónico?' diff --git a/sites/backend/src/templates/email/fr.json b/sites/backend/src/templates/email/fr.json new file mode 100644 index 00000000000..f708de31382 --- /dev/null +++ b/sites/backend/src/templates/email/fr.json @@ -0,0 +1,10 @@ +{ + "greeting": "bise", + "ps-pre-link": "FreeSewing est gratuit (duh), mais s'il te plaît...", + "ps-link": "devenir mécène", + "ps-post-link": "si tu peux te le permettre.", + "text-ps": "FreeSewing est gratuit (duh), mais deviens un mécène si tu peux te le permettre.", + "notMarketing": "Il ne s'agit pas de marketing, mais d'un email transactionnel concernant ton compte FreeSewing.", + "seeWhy": "Pour plus d'infos, voir :", + "whyDidIGetThis": "Pourquoi ai-je reçu cet e-mail ?" +} diff --git a/sites/backend/src/templates/email/fr.yaml b/sites/backend/src/templates/email/fr.yaml deleted file mode 100644 index 56b61150b4f..00000000000 --- a/sites/backend/src/templates/email/fr.yaml +++ /dev/null @@ -1,9 +0,0 @@ -#Shared -greeting: bise -ps-pre-link: FreeSewing est gratuit (duh), mais s'il te plaît... -ps-link: devenir mécène -ps-post-link: si tu peux te le permettre. -text-ps: 'FreeSewing est gratuit (duh), mais deviens un mécène si tu peux te le permettre.' -notMarketing: Il ne s'agit pas de marketing, mais d'un email transactionnel concernant ton compte FreeSewing. -seeWhy: 'Pour plus d''infos, voir :' -whyDidIGetThis: Pourquoi ai-je reçu cet e-mail ? diff --git a/sites/backend/src/templates/email/goodbye/de.json b/sites/backend/src/templates/email/goodbye/de.json new file mode 100644 index 00000000000..2d3d11b106b --- /dev/null +++ b/sites/backend/src/templates/email/goodbye/de.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Abschied nehmen", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/goodbye/de.yaml b/sites/backend/src/templates/email/goodbye/de.yaml deleted file mode 100644 index c02a1318e99..00000000000 --- a/sites/backend/src/templates/email/goodbye/de.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Abschied nehmen' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/goodbye/en.json b/sites/backend/src/templates/email/goodbye/en.json new file mode 100644 index 00000000000..43ebde6cddd --- /dev/null +++ b/sites/backend/src/templates/email/goodbye/en.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Farewell", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/goodbye/en.yaml b/sites/backend/src/templates/email/goodbye/en.yaml deleted file mode 100644 index c1bd9e918fe..00000000000 --- a/sites/backend/src/templates/email/goodbye/en.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Farewell' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/goodbye/es.json b/sites/backend/src/templates/email/goodbye/es.json new file mode 100644 index 00000000000..ecfc7ce06aa --- /dev/null +++ b/sites/backend/src/templates/email/goodbye/es.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Adiós", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/goodbye/es.yaml b/sites/backend/src/templates/email/goodbye/es.yaml deleted file mode 100644 index bade69c7bf3..00000000000 --- a/sites/backend/src/templates/email/goodbye/es.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Adiós' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/goodbye/fr.json b/sites/backend/src/templates/email/goodbye/fr.json new file mode 100644 index 00000000000..fba458b7397 --- /dev/null +++ b/sites/backend/src/templates/email/goodbye/fr.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Adieu", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/goodbye/fr.yaml b/sites/backend/src/templates/email/goodbye/fr.yaml deleted file mode 100644 index dbf0eedc396..00000000000 --- a/sites/backend/src/templates/email/goodbye/fr.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Adieu' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/goodbye/index.mjs b/sites/backend/src/templates/email/goodbye/index.mjs index 65734e78df0..0c7564c1798 100644 --- a/sites/backend/src/templates/email/goodbye/index.mjs +++ b/sites/backend/src/templates/email/goodbye/index.mjs @@ -1,10 +1,11 @@ import { headingRow, wrap } from '../shared/blocks.mjs' // Translations -import en from '../../../../public/locales/en/goodbye.json' assert { type: 'json' } -import de from '../../../../public/locales/de/goodbye.json' assert { type: 'json' } -import es from '../../../../public/locales/es/goodbye.json' assert { type: 'json' } -import fr from '../../../../public/locales/fr/goodbye.json' assert { type: 'json' } -import nl from '../../../../public/locales/nl/goodbye.json' assert { type: 'json' } +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } export const goodbye = { html: wrap.html(` @@ -35,4 +36,4 @@ joost PS: {{ps}}`), } -export const translations = { en, de, es, fr, nl } +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/goodbye/nl.json b/sites/backend/src/templates/email/goodbye/nl.json new file mode 100644 index 00000000000..9bba35213fd --- /dev/null +++ b/sites/backend/src/templates/email/goodbye/nl.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Vaarwel", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/goodbye/nl.yaml b/sites/backend/src/templates/email/goodbye/nl.yaml deleted file mode 100644 index 16fcf37573e..00000000000 --- a/sites/backend/src/templates/email/goodbye/nl.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Vaarwel' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/goodbye/uk.json b/sites/backend/src/templates/email/goodbye/uk.json new file mode 100644 index 00000000000..b49d7e65e23 --- /dev/null +++ b/sites/backend/src/templates/email/goodbye/uk.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Прощавай.", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/goodbye/uk.yaml b/sites/backend/src/templates/email/goodbye/uk.yaml deleted file mode 100644 index 7ecd60f8bc9..00000000000 --- a/sites/backend/src/templates/email/goodbye/uk.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Прощавай.' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/index.mjs b/sites/backend/src/templates/email/index.mjs index d00d20e2c3c..5ff7eb01be5 100644 --- a/sites/backend/src/templates/email/index.mjs +++ b/sites/backend/src/templates/email/index.mjs @@ -1,19 +1,22 @@ import { emailchange, translations as emailchangeTranslations } from './emailchange/index.mjs' import { goodbye, translations as goodbyeTranslations } from './goodbye/index.mjs' import { signinlink, translations as signinlinkTranslations } from './signinlink/index.mjs' -import { newslettersub, translations as newslettersubTranslations } from './newslettersub/index.mjs' import { passwordreset, translations as passwordresetTranslations } from './passwordreset/index.mjs' import { signup, translations as signupTranslations } from './signup/index.mjs' import { signupaea, translations as signupaeaTranslations } from './signup-aea/index.mjs' import { signupaed, translations as signupaedTranslations } from './signup-aed/index.mjs' import { transinvite, translations as transinviteTranslations } from './transinvite/index.mjs' import { langsuggest } from './langsuggest/index.mjs' +import { nlsub, translations as nlsubTranslations } from './nlsub/index.mjs' +import { nlsubact, translations as nlsubactTranslations } from './nlsubact/index.mjs' +import { nlsubinact, translations as nlsubinactTranslations } from './nlsubinact/index.mjs' // Shared translations -import en from '../../../public/locales/en/email.json' assert { type: 'json' } -import de from '../../../public/locales/de/email.json' assert { type: 'json' } -import es from '../../../public/locales/es/email.json' assert { type: 'json' } -import fr from '../../../public/locales/fr/email.json' assert { type: 'json' } -import nl from '../../../public/locales/nl/email.json' assert { type: 'json' } +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } /* * Everything is kept lowercase here because these key names are used in URLS @@ -22,13 +25,15 @@ export const templates = { emailchange, goodbye, signinlink, - newslettersub, passwordreset, signup, 'signup-aea': signupaea, 'signup-aed': signupaed, transinvite, langsuggest, + nlsub, + nlsubact, + nlsubinact, } /* @@ -47,12 +52,14 @@ export const translations = { emailchange: emailchangeTranslations, goodbye: goodbyeTranslations, signinlink: signinlinkTranslations, - newslettersub: newslettersubTranslations, passwordreset: passwordresetTranslations, signup: signupTranslations, 'signup-aea': signupaeaTranslations, 'signup-aed': signupaedTranslations, transinvite: transinviteTranslations, langsuggest: noTranslations, - shared: { en, de, es, fr, nl }, + nlsub: nlsubTranslations, + nlsubact: nlsubactTranslations, + nlsubinact: nlsubinactTranslations, + shared: { en, de, es, fr, nl, uk }, } diff --git a/sites/backend/src/templates/email/newslettersub/de.yaml b/sites/backend/src/templates/email/newslettersub/de.yaml deleted file mode 100644 index 67cf759995e..00000000000 --- a/sites/backend/src/templates/email/newslettersub/de.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] newsletter sub fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/newslettersub/en.yaml b/sites/backend/src/templates/email/newslettersub/en.yaml deleted file mode 100644 index 67cf759995e..00000000000 --- a/sites/backend/src/templates/email/newslettersub/en.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] newsletter sub fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/newslettersub/es.yaml b/sites/backend/src/templates/email/newslettersub/es.yaml deleted file mode 100644 index 6b4b76c5da0..00000000000 --- a/sites/backend/src/templates/email/newslettersub/es.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] boletín sub fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/newslettersub/fr.yaml b/sites/backend/src/templates/email/newslettersub/fr.yaml deleted file mode 100644 index 67cf759995e..00000000000 --- a/sites/backend/src/templates/email/newslettersub/fr.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] newsletter sub fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/newslettersub/index.mjs b/sites/backend/src/templates/email/newslettersub/index.mjs deleted file mode 100644 index 0c2eb10aaa9..00000000000 --- a/sites/backend/src/templates/email/newslettersub/index.mjs +++ /dev/null @@ -1,24 +0,0 @@ -import { buttonRow, closingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs' -// Translations -import en from '../../../../public/locales/en/newslettersub.json' assert { type: 'json' } -import de from '../../../../public/locales/de/newslettersub.json' assert { type: 'json' } -import es from '../../../../public/locales/es/newslettersub.json' assert { type: 'json' } -import fr from '../../../../public/locales/fr/newslettersub.json' assert { type: 'json' } -import nl from '../../../../public/locales/nl/newslettersub.json' assert { type: 'json' } - -export const newslettersub = { - html: wrap.html(` - ${headingRow.html} - ${lead1Row.html} - ${buttonRow.html} - ${closingRow.html} -`), - text: wrap.text(` -${headingRow.text} -${lead1Row.text} -${buttonRow.text} -${closingRow.text} -`), -} - -export const translations = { en, de, es, fr, nl } diff --git a/sites/backend/src/templates/email/newslettersub/nl.yaml b/sites/backend/src/templates/email/newslettersub/nl.yaml deleted file mode 100644 index 5fdbc7c49bf..00000000000 --- a/sites/backend/src/templates/email/newslettersub/nl.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] nieuwsbrief sub fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/newslettersub/uk.yaml b/sites/backend/src/templates/email/newslettersub/uk.yaml deleted file mode 100644 index 22c75ebc1dc..00000000000 --- a/sites/backend/src/templates/email/newslettersub/uk.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] інформаційний бюлетень sub fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/nl.json b/sites/backend/src/templates/email/nl.json new file mode 100644 index 00000000000..0f62e7e5709 --- /dev/null +++ b/sites/backend/src/templates/email/nl.json @@ -0,0 +1,10 @@ +{ + "greeting": "liefs", + "ps-pre-link": "FreeSewing is gratis (duh), maar alsjeblieft", + "ps-link": "word mecenas", + "ps-post-link": "als je het je kunt veroorloven.", + "text-ps": "FreeSewing is gratis (duh), maar word alsjeblieft beschermer als je het je kunt veroorloven.", + "notMarketing": "Dit is geen marketing, maar een transactie-e-mail over je FreeSewing account.", + "seeWhy": "Zie voor meer informatie:", + "whyDidIGetThis": "Waarom kreeg ik deze e-mail?" +} diff --git a/sites/backend/src/templates/email/nl.yaml b/sites/backend/src/templates/email/nl.yaml deleted file mode 100644 index 16406241d96..00000000000 --- a/sites/backend/src/templates/email/nl.yaml +++ /dev/null @@ -1,9 +0,0 @@ -#Shared -greeting: liefs -ps-pre-link: FreeSewing is gratis (duh), maar alsjeblieft -ps-link: word mecenas -ps-post-link: als je het je kunt veroorloven. -text-ps: 'FreeSewing is gratis (duh), maar word alsjeblieft beschermer als je het je kunt veroorloven.' -notMarketing: Dit is geen marketing, maar een transactie-e-mail over je FreeSewing account. -seeWhy: 'Zie voor meer informatie:' -whyDidIGetThis: Waarom kreeg ik deze e-mail? diff --git a/sites/backend/src/templates/email/nlsub/de.json b/sites/backend/src/templates/email/nlsub/de.json new file mode 100644 index 00000000000..bacf8f8b28b --- /dev/null +++ b/sites/backend/src/templates/email/nlsub/de.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsub/en.json b/sites/backend/src/templates/email/nlsub/en.json new file mode 100644 index 00000000000..bacf8f8b28b --- /dev/null +++ b/sites/backend/src/templates/email/nlsub/en.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsub/es.json b/sites/backend/src/templates/email/nlsub/es.json new file mode 100644 index 00000000000..bacf8f8b28b --- /dev/null +++ b/sites/backend/src/templates/email/nlsub/es.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsub/fr.json b/sites/backend/src/templates/email/nlsub/fr.json new file mode 100644 index 00000000000..bacf8f8b28b --- /dev/null +++ b/sites/backend/src/templates/email/nlsub/fr.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsub/index.mjs b/sites/backend/src/templates/email/nlsub/index.mjs new file mode 100644 index 00000000000..4c2c9a4c395 --- /dev/null +++ b/sites/backend/src/templates/email/nlsub/index.mjs @@ -0,0 +1,25 @@ +import { buttonRow, newsletterClosingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs' +// Translations +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } + +export const nlsub = { + html: wrap.html(` + ${headingRow.html} + ${lead1Row.html} + ${buttonRow.html} + ${newsletterClosingRow.html} +`), + text: wrap.text(` +${headingRow.text} +${lead1Row.text} +${buttonRow.text} +${newsletterClosingRow.text} +`), +} + +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/nlsub/nl.json b/sites/backend/src/templates/email/nlsub/nl.json new file mode 100644 index 00000000000..bacf8f8b28b --- /dev/null +++ b/sites/backend/src/templates/email/nlsub/nl.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsub/uk.json b/sites/backend/src/templates/email/nlsub/uk.json new file mode 100644 index 00000000000..bacf8f8b28b --- /dev/null +++ b/sites/backend/src/templates/email/nlsub/uk.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubact/de.json b/sites/backend/src/templates/email/nlsubact/de.json new file mode 100644 index 00000000000..21641f84e47 --- /dev/null +++ b/sites/backend/src/templates/email/nlsubact/de.json @@ -0,0 +1,6 @@ +{ + "subject": "[FreeSewing] You are already subscribed to our newsletter", + "heading": "You are already subscribed", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. But you are already subscribed, so there is nothing to do here.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubact/en.json b/sites/backend/src/templates/email/nlsubact/en.json new file mode 100644 index 00000000000..21641f84e47 --- /dev/null +++ b/sites/backend/src/templates/email/nlsubact/en.json @@ -0,0 +1,6 @@ +{ + "subject": "[FreeSewing] You are already subscribed to our newsletter", + "heading": "You are already subscribed", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. But you are already subscribed, so there is nothing to do here.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubact/es.json b/sites/backend/src/templates/email/nlsubact/es.json new file mode 100644 index 00000000000..21641f84e47 --- /dev/null +++ b/sites/backend/src/templates/email/nlsubact/es.json @@ -0,0 +1,6 @@ +{ + "subject": "[FreeSewing] You are already subscribed to our newsletter", + "heading": "You are already subscribed", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. But you are already subscribed, so there is nothing to do here.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubact/fr.json b/sites/backend/src/templates/email/nlsubact/fr.json new file mode 100644 index 00000000000..21641f84e47 --- /dev/null +++ b/sites/backend/src/templates/email/nlsubact/fr.json @@ -0,0 +1,6 @@ +{ + "subject": "[FreeSewing] You are already subscribed to our newsletter", + "heading": "You are already subscribed", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. But you are already subscribed, so there is nothing to do here.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubact/index.mjs b/sites/backend/src/templates/email/nlsubact/index.mjs new file mode 100644 index 00000000000..83b6f7364db --- /dev/null +++ b/sites/backend/src/templates/email/nlsubact/index.mjs @@ -0,0 +1,23 @@ +import { buttonRow, closingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs' +// Translations +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } + +export const nlsubact = { + html: wrap.html(` + ${headingRow.html} + ${lead1Row.html} + ${closingRow.html} +`), + text: wrap.text(` +${headingRow.text} +${lead1Row.text} +${closingRow.text} +`), +} + +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/nlsubact/nl.json b/sites/backend/src/templates/email/nlsubact/nl.json new file mode 100644 index 00000000000..21641f84e47 --- /dev/null +++ b/sites/backend/src/templates/email/nlsubact/nl.json @@ -0,0 +1,6 @@ +{ + "subject": "[FreeSewing] You are already subscribed to our newsletter", + "heading": "You are already subscribed", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. But you are already subscribed, so there is nothing to do here.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubact/uk.json b/sites/backend/src/templates/email/nlsubact/uk.json new file mode 100644 index 00000000000..21641f84e47 --- /dev/null +++ b/sites/backend/src/templates/email/nlsubact/uk.json @@ -0,0 +1,6 @@ +{ + "subject": "[FreeSewing] You are already subscribed to our newsletter", + "heading": "You are already subscribed", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. But you are already subscribed, so there is nothing to do here.", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubinact/de.json b/sites/backend/src/templates/email/nlsubinact/de.json new file mode 100644 index 00000000000..c38b86c95db --- /dev/null +++ b/sites/backend/src/templates/email/nlsubinact/de.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. (note that we already had a pending subscription for this address).", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubinact/en.json b/sites/backend/src/templates/email/nlsubinact/en.json new file mode 100644 index 00000000000..c38b86c95db --- /dev/null +++ b/sites/backend/src/templates/email/nlsubinact/en.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. (note that we already had a pending subscription for this address).", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubinact/es.json b/sites/backend/src/templates/email/nlsubinact/es.json new file mode 100644 index 00000000000..c38b86c95db --- /dev/null +++ b/sites/backend/src/templates/email/nlsubinact/es.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. (note that we already had a pending subscription for this address).", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubinact/fr.json b/sites/backend/src/templates/email/nlsubinact/fr.json new file mode 100644 index 00000000000..c38b86c95db --- /dev/null +++ b/sites/backend/src/templates/email/nlsubinact/fr.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. (note that we already had a pending subscription for this address).", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubinact/index.mjs b/sites/backend/src/templates/email/nlsubinact/index.mjs new file mode 100644 index 00000000000..f6ec3e3632e --- /dev/null +++ b/sites/backend/src/templates/email/nlsubinact/index.mjs @@ -0,0 +1,25 @@ +import { buttonRow, newsletterClosingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs' +// Translations +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } + +export const nlsubinact = { + html: wrap.html(` + ${headingRow.html} + ${lead1Row.html} + ${buttonRow.html} + ${newsletterClosingRow.html} +`), + text: wrap.text(` +${headingRow.text} +${lead1Row.text} +${buttonRow.text} +${newsletterClosingRow.text} +`), +} + +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/nlsubinact/nl.json b/sites/backend/src/templates/email/nlsubinact/nl.json new file mode 100644 index 00000000000..c38b86c95db --- /dev/null +++ b/sites/backend/src/templates/email/nlsubinact/nl.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. (note that we already had a pending subscription for this address).", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/nlsubinact/uk.json b/sites/backend/src/templates/email/nlsubinact/uk.json new file mode 100644 index 00000000000..c38b86c95db --- /dev/null +++ b/sites/backend/src/templates/email/nlsubinact/uk.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Confirm your newsletter subscription", + "heading": "Please confirm your newsletter subscription", + "lead": "To confirm your subscription to the FreeSewing newsletter, click the big rectangle below:", + "text-lead": "To confirm your subscription to the FreeSewing newsletter, click the link below:", + "button": "Confirm subscription", + "closing": "You (or someone else) tried to subscribe this email address to the FreeSewing newsletter just now. (note that we already had a pending subscription for this address).", + "greeting": "love," +} diff --git a/sites/backend/src/templates/email/passwordreset/de.json b/sites/backend/src/templates/email/passwordreset/de.json new file mode 100644 index 00000000000..ae84112d8f4 --- /dev/null +++ b/sites/backend/src/templates/email/passwordreset/de.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Passwort zurücksetzen fixme", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/passwordreset/de.yaml b/sites/backend/src/templates/email/passwordreset/de.yaml deleted file mode 100644 index 9fd45913f4c..00000000000 --- a/sites/backend/src/templates/email/passwordreset/de.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Passwort zurücksetzen fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/passwordreset/en.json b/sites/backend/src/templates/email/passwordreset/en.json new file mode 100644 index 00000000000..c7d6073d237 --- /dev/null +++ b/sites/backend/src/templates/email/passwordreset/en.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] passwordreset fixme", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/passwordreset/en.yaml b/sites/backend/src/templates/email/passwordreset/en.yaml deleted file mode 100644 index f4ad0c51f2d..00000000000 --- a/sites/backend/src/templates/email/passwordreset/en.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] passwordreset fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/passwordreset/es.json b/sites/backend/src/templates/email/passwordreset/es.json new file mode 100644 index 00000000000..c7d6073d237 --- /dev/null +++ b/sites/backend/src/templates/email/passwordreset/es.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] passwordreset fixme", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/passwordreset/es.yaml b/sites/backend/src/templates/email/passwordreset/es.yaml deleted file mode 100644 index f4ad0c51f2d..00000000000 --- a/sites/backend/src/templates/email/passwordreset/es.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] passwordreset fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/passwordreset/fr.json b/sites/backend/src/templates/email/passwordreset/fr.json new file mode 100644 index 00000000000..c7d6073d237 --- /dev/null +++ b/sites/backend/src/templates/email/passwordreset/fr.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] passwordreset fixme", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/passwordreset/fr.yaml b/sites/backend/src/templates/email/passwordreset/fr.yaml deleted file mode 100644 index f4ad0c51f2d..00000000000 --- a/sites/backend/src/templates/email/passwordreset/fr.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] passwordreset fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/passwordreset/index.mjs b/sites/backend/src/templates/email/passwordreset/index.mjs index d91befd3d5f..3082a287880 100644 --- a/sites/backend/src/templates/email/passwordreset/index.mjs +++ b/sites/backend/src/templates/email/passwordreset/index.mjs @@ -1,10 +1,11 @@ import { buttonRow, closingRow, headingRow, wrap } from '../shared/blocks.mjs' // Translations -import en from '../../../../public/locales/en/passwordreset.json' assert { type: 'json' } -import de from '../../../../public/locales/de/passwordreset.json' assert { type: 'json' } -import es from '../../../../public/locales/es/passwordreset.json' assert { type: 'json' } -import fr from '../../../../public/locales/fr/passwordreset.json' assert { type: 'json' } -import nl from '../../../../public/locales/nl/passwordreset.json' assert { type: 'json' } +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } export const passwordreset = { html: wrap.html(` @@ -34,4 +35,4 @@ ${closingRow.text} `), } -export const translations = { en, de, es, fr, nl } +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/passwordreset/nl.json b/sites/backend/src/templates/email/passwordreset/nl.json new file mode 100644 index 00000000000..ba39a3ce8e2 --- /dev/null +++ b/sites/backend/src/templates/email/passwordreset/nl.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] wachtwoord opnieuw instellen fixme", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/passwordreset/nl.yaml b/sites/backend/src/templates/email/passwordreset/nl.yaml deleted file mode 100644 index 9defb87ab1f..00000000000 --- a/sites/backend/src/templates/email/passwordreset/nl.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] wachtwoord opnieuw instellen fixme' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/passwordreset/uk.json b/sites/backend/src/templates/email/passwordreset/uk.json new file mode 100644 index 00000000000..39e097d00e1 --- /dev/null +++ b/sites/backend/src/templates/email/passwordreset/uk.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] виправлення скидання паролю", + "heading": "FIXME", + "lead": "fixme", + "text-lead": "fixme", + "closing": "fixme" +} diff --git a/sites/backend/src/templates/email/passwordreset/uk.yaml b/sites/backend/src/templates/email/passwordreset/uk.yaml deleted file mode 100644 index 697761d66e5..00000000000 --- a/sites/backend/src/templates/email/passwordreset/uk.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] виправлення скидання паролю' -heading: FIXME -lead: fixme -text-lead: fixme -closing: fixme diff --git a/sites/backend/src/templates/email/shared/blocks.mjs b/sites/backend/src/templates/email/shared/blocks.mjs index d8de4ea55aa..57dd08849dd 100644 --- a/sites/backend/src/templates/email/shared/blocks.mjs +++ b/sites/backend/src/templates/email/shared/blocks.mjs @@ -41,6 +41,32 @@ joost PS: {{{ text-ps }}} : {{{ supportUrl }}}`, } +export const newsletterClosingRow = { + html: ` + + +

+ {{ closing }} +

+ {{ greeting }} +
+ joost +

+ PS: {{ ps-pre-link}} + + {{ ps-link}} + {{ ps-post-link }} +

+ + `, + text: ` +{{{ closing }}} + +{{{ greeting }}} +joost +`, +} + export const headingRow = { html: ` diff --git a/sites/backend/src/templates/email/signinlink/de.json b/sites/backend/src/templates/email/signinlink/de.json new file mode 100644 index 00000000000..ab305e42e19 --- /dev/null +++ b/sites/backend/src/templates/email/signinlink/de.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Dein Anmeldelink für FreeSewing.org", + "heading": "Ein geheimer Zugangslink, nur für dich", + "lead": "Um dich bei FreeSewing.org anzumelden, klicke auf das große schwarze Rechteck unten:", + "text-lead": "Um dich bei FreeSewing.org anzumelden, klicke auf den Link unten:", + "button": "Anmelden", + "closing": "Gib diese E-Mail nicht weiter, sie ist wirklich nur für dich." +} diff --git a/sites/backend/src/templates/email/signinlink/de.yaml b/sites/backend/src/templates/email/signinlink/de.yaml deleted file mode 100644 index 3162e902551..00000000000 --- a/sites/backend/src/templates/email/signinlink/de.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Dein Anmeldelink für FreeSewing.org" -heading: Ein geheimer Zugangslink, nur für dich -lead: 'Um dich bei FreeSewing.org anzumelden, klicke auf das große schwarze Rechteck unten:' -text-lead: 'Um dich bei FreeSewing.org anzumelden, klicke auf den Link unten:' -button: Anmelden -closing: Gib diese E-Mail nicht weiter, sie ist wirklich nur für dich. diff --git a/sites/backend/src/templates/email/signinlink/en.json b/sites/backend/src/templates/email/signinlink/en.json new file mode 100644 index 00000000000..691ba48f36c --- /dev/null +++ b/sites/backend/src/templates/email/signinlink/en.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Your sign-in link for FreeSewing.org", + "heading": "A secret access link, just for you", + "lead": "To sign in to FreeSewing.org, click the big black rectangle below:", + "text-lead": "To sign in to FreeSewing.org, click the link below:", + "button": "Sign in", + "closing": "Do not share this email, it really is just for you." +} diff --git a/sites/backend/src/templates/email/signinlink/en.yaml b/sites/backend/src/templates/email/signinlink/en.yaml deleted file mode 100644 index bd327ad18ae..00000000000 --- a/sites/backend/src/templates/email/signinlink/en.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Your sign-in link for FreeSewing.org" -heading: A secret access link, just for you -lead: 'To sign in to FreeSewing.org, click the big black rectangle below:' -text-lead: 'To sign in to FreeSewing.org, click the link below:' -button: Sign in -closing: Do not share this email, it really is just for you. diff --git a/sites/backend/src/templates/email/signinlink/es.json b/sites/backend/src/templates/email/signinlink/es.json new file mode 100644 index 00000000000..130bda05ada --- /dev/null +++ b/sites/backend/src/templates/email/signinlink/es.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Tu enlace de acceso a FreeSewing.org", + "heading": "Un enlace de acceso secreto, sólo para ti", + "lead": "Para iniciar sesión en FreeSewing.org, haz clic en el rectángulo negro grande de abajo:", + "text-lead": "Para iniciar sesión en FreeSewing.org, haz clic en el enlace siguiente:", + "button": "Inicia sesión", + "closing": "No compartas este correo electrónico, es realmente sólo para ti." +} diff --git a/sites/backend/src/templates/email/signinlink/es.yaml b/sites/backend/src/templates/email/signinlink/es.yaml deleted file mode 100644 index 3c371f06814..00000000000 --- a/sites/backend/src/templates/email/signinlink/es.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Tu enlace de acceso a FreeSewing.org" -heading: Un enlace de acceso secreto, sólo para ti -lead: 'Para iniciar sesión en FreeSewing.org, haz clic en el rectángulo negro grande de abajo:' -text-lead: 'Para iniciar sesión en FreeSewing.org, haz clic en el enlace siguiente:' -button: Inicia sesión -closing: No compartas este correo electrónico, es realmente sólo para ti. diff --git a/sites/backend/src/templates/email/signinlink/fr.json b/sites/backend/src/templates/email/signinlink/fr.json new file mode 100644 index 00000000000..185ba9f45e1 --- /dev/null +++ b/sites/backend/src/templates/email/signinlink/fr.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Ton lien de connexion à FreeSewing.org", + "heading": "Un lien d'accès secret, juste pour toi", + "lead": "Pour te connecter à FreeSewing.org, clique sur le grand rectangle noir ci-dessous :", + "text-lead": "Pour te connecter à FreeSewing.org, clique sur le lien ci-dessous :", + "button": "Connexion", + "closing": "Ne partage pas cet email, il est vraiment juste pour toi." +} diff --git a/sites/backend/src/templates/email/signinlink/fr.yaml b/sites/backend/src/templates/email/signinlink/fr.yaml deleted file mode 100644 index 3e715ffe20e..00000000000 --- a/sites/backend/src/templates/email/signinlink/fr.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Ton lien de connexion à FreeSewing.org" -heading: Un lien d'accès secret, juste pour toi -lead: 'Pour te connecter à FreeSewing.org, clique sur le grand rectangle noir ci-dessous :' -text-lead: 'Pour te connecter à FreeSewing.org, clique sur le lien ci-dessous :' -button: Connexion -closing: Ne partage pas cet email, il est vraiment juste pour toi. diff --git a/sites/backend/src/templates/email/signinlink/index.mjs b/sites/backend/src/templates/email/signinlink/index.mjs index 961a2cdd685..9d9ce30e81c 100644 --- a/sites/backend/src/templates/email/signinlink/index.mjs +++ b/sites/backend/src/templates/email/signinlink/index.mjs @@ -1,10 +1,11 @@ import { buttonRow, closingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs' // Translations -import en from '../../../../public/locales/en/signinlink.json' assert { type: 'json' } -import de from '../../../../public/locales/de/signinlink.json' assert { type: 'json' } -import es from '../../../../public/locales/es/signinlink.json' assert { type: 'json' } -import fr from '../../../../public/locales/fr/signinlink.json' assert { type: 'json' } -import nl from '../../../../public/locales/nl/signinlink.json' assert { type: 'json' } +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } export const signinlink = { html: wrap.html(` @@ -29,4 +30,4 @@ PS: {{{ text-ps }}} : {{{ supportUrl }}} `), } -export const translations = { en, de, es, fr, nl } +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/signinlink/nl.json b/sites/backend/src/templates/email/signinlink/nl.json new file mode 100644 index 00000000000..81b37ae1c6c --- /dev/null +++ b/sites/backend/src/templates/email/signinlink/nl.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Je aanmeldlink voor FreeSewing.org", + "heading": "Een geheime toegangslink, speciaal voor jou", + "lead": "Klik op de grote zwarte rechthoek hieronder om je aan te melden bij FreeSewing.org:", + "text-lead": "Klik op de onderstaande link om je aan te melden bij FreeSewing.org:", + "button": "Aanmelden", + "closing": "Deel deze e-mail niet, hij is echt alleen voor jou." +} diff --git a/sites/backend/src/templates/email/signinlink/nl.yaml b/sites/backend/src/templates/email/signinlink/nl.yaml deleted file mode 100644 index 3c833df625c..00000000000 --- a/sites/backend/src/templates/email/signinlink/nl.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Je aanmeldlink voor FreeSewing.org" -heading: Een geheime toegangslink, speciaal voor jou -lead: 'Klik op de grote zwarte rechthoek hieronder om je aan te melden bij FreeSewing.org:' -text-lead: 'Klik op de onderstaande link om je aan te melden bij FreeSewing.org:' -button: Aanmelden -closing: Deel deze e-mail niet, hij is echt alleen voor jou. diff --git a/sites/backend/src/templates/email/signinlink/uk.json b/sites/backend/src/templates/email/signinlink/uk.json new file mode 100644 index 00000000000..65d2d1751ec --- /dev/null +++ b/sites/backend/src/templates/email/signinlink/uk.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Ваше посилання для входу на FreeSewing.org", + "heading": "Секретне посилання доступу, тільки для вас", + "lead": "Щоб увійти на FreeSewing.org, натисніть великий чорний прямокутник нижче:", + "text-lead": "Щоб увійти на FreeSewing.org, натисніть на посилання нижче:", + "button": "Вхід", + "closing": "Не діліться цим листом, він дійсно тільки для вас." +} diff --git a/sites/backend/src/templates/email/signinlink/uk.yaml b/sites/backend/src/templates/email/signinlink/uk.yaml deleted file mode 100644 index 1f5ccfb3479..00000000000 --- a/sites/backend/src/templates/email/signinlink/uk.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Ваше посилання для входу на FreeSewing.org" -heading: Секретне посилання доступу, тільки для вас -lead: 'Щоб увійти на FreeSewing.org, натисніть великий чорний прямокутник нижче:' -text-lead: 'Щоб увійти на FreeSewing.org, натисніть на посилання нижче:' -button: Вхід -closing: Не діліться цим листом, він дійсно тільки для вас. diff --git a/sites/backend/src/templates/email/signup-aea/de.json b/sites/backend/src/templates/email/signup-aea/de.json new file mode 100644 index 00000000000..1a5c18f702a --- /dev/null +++ b/sites/backend/src/templates/email/signup-aea/de.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Du musst dich nicht registrieren, du bist schon an Bord", + "heading": "Willkommen zurück bei FreeSewing", + "preLead": "Jemand (du?) hat versucht, sich mit dieser E-Mail-Adresse zu registrieren. Aber wir haben bereits ein aktives Konto, das mit dieser E-Mail-Adresse verknüpft ist.", + "lead": "Um dich in dein Konto einzuloggen, klicke auf den großen schwarzen Button unten:", + "text-lead": "Um dich in dein Konto einzuloggen, klicke auf den Link unten:", + "button": "Anmelden", + "closing": "Mehr muss nicht getan werden." +} diff --git a/sites/backend/src/templates/email/signup-aea/de.yaml b/sites/backend/src/templates/email/signup-aea/de.yaml deleted file mode 100644 index 46f73b2db1c..00000000000 --- a/sites/backend/src/templates/email/signup-aea/de.yaml +++ /dev/null @@ -1,7 +0,0 @@ -subject: "[FreeSewing] Du musst dich nicht registrieren, du bist schon an Bord" -heading: Willkommen zurück bei FreeSewing -preLead: 'Jemand (du?) hat versucht, sich mit dieser E-Mail-Adresse zu registrieren. Aber wir haben bereits ein aktives Konto, das mit dieser E-Mail-Adresse verknüpft ist.' -lead: 'Um dich in dein Konto einzuloggen, klicke auf den großen schwarzen Button unten:' -text-lead: 'Um dich in dein Konto einzuloggen, klicke auf den Link unten:' -button: Anmelden -closing: "Mehr muss nicht getan werden." diff --git a/sites/backend/src/templates/email/signup-aea/en.json b/sites/backend/src/templates/email/signup-aea/en.json new file mode 100644 index 00000000000..b71b264d781 --- /dev/null +++ b/sites/backend/src/templates/email/signup-aea/en.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] No need to sign up, you're already in", + "heading": "Welcome back to FreeSewing", + "preLead": "Someone (you?) tried to sign up with this email address. But we already have an active account tied to this email.", + "lead": "To log in to your account, click the big black button below:", + "text-lead": "To log in to your account, click the link below:", + "button": "Log in", + "closing": "That's all it takes." +} diff --git a/sites/backend/src/templates/email/signup-aea/en.yaml b/sites/backend/src/templates/email/signup-aea/en.yaml deleted file mode 100644 index edff52d6da4..00000000000 --- a/sites/backend/src/templates/email/signup-aea/en.yaml +++ /dev/null @@ -1,7 +0,0 @@ -subject: "[FreeSewing] No need to sign up, you're already in" -heading: Welcome back to FreeSewing -preLead: 'Someone (you?) tried to sign up with this email address. But we already have an active account tied to this email.' -lead: 'To log in to your account, click the big black button below:' -text-lead: 'To log in to your account, click the link below:' -button: Log in -closing: "That's all it takes." diff --git a/sites/backend/src/templates/email/signup-aea/es.json b/sites/backend/src/templates/email/signup-aea/es.json new file mode 100644 index 00000000000..4817751f3a8 --- /dev/null +++ b/sites/backend/src/templates/email/signup-aea/es.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] No hace falta que te inscribas, ya estás dentro", + "heading": "Bienvenido de nuevo a FreeSewing", + "preLead": "Alguien (¿tú?) ha intentado registrarse con esta dirección de correo electrónico. Pero ya tenemos una cuenta activa vinculada a este correo electrónico.", + "lead": "Para acceder a tu cuenta, haz clic en el botón negro grande de abajo:", + "text-lead": "Para acceder a tu cuenta, haz clic en el siguiente enlace:", + "button": "Iniciar sesión", + "closing": "Eso es todo lo que hace falta." +} diff --git a/sites/backend/src/templates/email/signup-aea/es.yaml b/sites/backend/src/templates/email/signup-aea/es.yaml deleted file mode 100644 index 20aff952fc6..00000000000 --- a/sites/backend/src/templates/email/signup-aea/es.yaml +++ /dev/null @@ -1,7 +0,0 @@ -subject: "[FreeSewing] No hace falta que te inscribas, ya estás dentro" -heading: Bienvenido de nuevo a FreeSewing -preLead: 'Alguien (¿tú?) ha intentado registrarse con esta dirección de correo electrónico. Pero ya tenemos una cuenta activa vinculada a este correo electrónico.' -lead: 'Para acceder a tu cuenta, haz clic en el botón negro grande de abajo:' -text-lead: 'Para acceder a tu cuenta, haz clic en el siguiente enlace:' -button: Iniciar sesión -closing: "Eso es todo lo que hace falta." diff --git a/sites/backend/src/templates/email/signup-aea/fr.json b/sites/backend/src/templates/email/signup-aea/fr.json new file mode 100644 index 00000000000..1be3e5fae98 --- /dev/null +++ b/sites/backend/src/templates/email/signup-aea/fr.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Pas besoin de s'inscrire, tu es déjà inscrit", + "heading": "Bienvenue sur FreeSewing", + "preLead": "Quelqu'un (toi ?) a essayé de s'inscrire avec cette adresse e-mail. Mais nous avons déjà un compte actif lié à cet email.", + "lead": "Pour te connecter à ton compte, clique sur le gros bouton noir ci-dessous :", + "text-lead": "Pour te connecter à ton compte, clique sur le lien ci-dessous :", + "button": "Connexion", + "closing": "C'est tout ce qu'il faut." +} diff --git a/sites/backend/src/templates/email/signup-aea/fr.yaml b/sites/backend/src/templates/email/signup-aea/fr.yaml deleted file mode 100644 index e6b49d4f317..00000000000 --- a/sites/backend/src/templates/email/signup-aea/fr.yaml +++ /dev/null @@ -1,7 +0,0 @@ -subject: "[FreeSewing] Pas besoin de s'inscrire, tu es déjà inscrit" -heading: Bienvenue sur FreeSewing -preLead: 'Quelqu''un (toi ?) a essayé de s''inscrire avec cette adresse e-mail. Mais nous avons déjà un compte actif lié à cet email.' -lead: 'Pour te connecter à ton compte, clique sur le gros bouton noir ci-dessous :' -text-lead: 'Pour te connecter à ton compte, clique sur le lien ci-dessous :' -button: Connexion -closing: "C'est tout ce qu'il faut." diff --git a/sites/backend/src/templates/email/signup-aea/index.mjs b/sites/backend/src/templates/email/signup-aea/index.mjs index 7e49af81b2c..b5ad490d4bd 100644 --- a/sites/backend/src/templates/email/signup-aea/index.mjs +++ b/sites/backend/src/templates/email/signup-aea/index.mjs @@ -1,10 +1,11 @@ import { buttonRow, closingRow, headingRow, preLeadRow, wrap } from '../shared/blocks.mjs' // Translations -import en from '../../../../public/locales/en/signup-aea.json' assert { type: 'json' } -import de from '../../../../public/locales/de/signup-aea.json' assert { type: 'json' } -import es from '../../../../public/locales/es/signup-aea.json' assert { type: 'json' } -import fr from '../../../../public/locales/fr/signup-aea.json' assert { type: 'json' } -import nl from '../../../../public/locales/nl/signup-aea.json' assert { type: 'json' } +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } // aea = Account Exists and is Active export const signupaea = { @@ -32,4 +33,4 @@ PS: {{{ text-ps }}} : {{{ supportUrl }}} `), } -export const translations = { en, de, es, fr, nl } +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/signup-aea/nl.json b/sites/backend/src/templates/email/signup-aea/nl.json new file mode 100644 index 00000000000..273a4a5c3e5 --- /dev/null +++ b/sites/backend/src/templates/email/signup-aea/nl.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Je hoeft je niet aan te melden, je bent al binnen", + "heading": "Welkom terug bij FreeSewing", + "preLead": "Iemand (jij?) probeerde zich aan te melden met dit e-mailadres. Maar we hebben al een actieve account gekoppeld aan dit e-mailadres.", + "lead": "Klik op de grote zwarte knop hieronder om in te loggen op je account:", + "text-lead": "Klik op de onderstaande link om in te loggen op je account:", + "button": "Aanmelden", + "closing": "Langer hoeft dat niet te duren." +} diff --git a/sites/backend/src/templates/email/signup-aea/nl.yaml b/sites/backend/src/templates/email/signup-aea/nl.yaml deleted file mode 100644 index f0b0bbe29d8..00000000000 --- a/sites/backend/src/templates/email/signup-aea/nl.yaml +++ /dev/null @@ -1,7 +0,0 @@ -subject: "[FreeSewing] Je hoeft je niet aan te melden, je bent al binnen" -heading: Welkom terug bij FreeSewing -preLead: 'Iemand (jij?) probeerde zich aan te melden met dit e-mailadres. Maar we hebben al een actieve account gekoppeld aan dit e-mailadres.' -lead: 'Klik op de grote zwarte knop hieronder om in te loggen op je account:' -text-lead: 'Klik op de onderstaande link om in te loggen op je account:' -button: Aanmelden -closing: "Langer hoeft dat niet te duren." diff --git a/sites/backend/src/templates/email/signup-aea/uk.json b/sites/backend/src/templates/email/signup-aea/uk.json new file mode 100644 index 00000000000..0b598b4f34a --- /dev/null +++ b/sites/backend/src/templates/email/signup-aea/uk.json @@ -0,0 +1,9 @@ +{ + "subject": "[FreeSewing] Не потрібно реєструватися, ви вже є учасником", + "heading": "Ласкаво просимо до FreeSewing", + "preLead": "Хтось (ви?) намагався зареєструватися за цією адресою. Але у нас вже є активний акаунт, прив'язаний до цієї адреси.", + "lead": "Щоб увійти до свого облікового запису, натисніть велику чорну кнопку нижче:", + "text-lead": "Щоб увійти до свого облікового запису, натисніть на посилання нижче:", + "button": "Увійти", + "closing": "Це все, що потрібно." +} diff --git a/sites/backend/src/templates/email/signup-aea/uk.yaml b/sites/backend/src/templates/email/signup-aea/uk.yaml deleted file mode 100644 index 8fbfcc4634e..00000000000 --- a/sites/backend/src/templates/email/signup-aea/uk.yaml +++ /dev/null @@ -1,7 +0,0 @@ -subject: "[FreeSewing] Не потрібно реєструватися, ви вже є учасником" -heading: Ласкаво просимо до FreeSewing -preLead: 'Хтось (ви?) намагався зареєструватися за цією адресою. Але у нас вже є активний акаунт, прив''язаний до цієї адреси.' -lead: 'Щоб увійти до свого облікового запису, натисніть велику чорну кнопку нижче:' -text-lead: 'Щоб увійти до свого облікового запису, натисніть на посилання нижче:' -button: Увійти -closing: "Це все, що потрібно." diff --git a/sites/backend/src/templates/email/signup-aed/de.json b/sites/backend/src/templates/email/signup-aed/de.json new file mode 100644 index 00000000000..e61bbc06f79 --- /dev/null +++ b/sites/backend/src/templates/email/signup-aed/de.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Dein Konto ist als deaktiviert markiert", + "heading": "Dein FreeSewing-Konto ist deaktiviert", + "preLead": "Ein Konto kann deaktiviert werden, wenn ein/e Nutzer/in seine/ihre Zustimmung widerruft oder (in Ausnahmefällen) wenn ein/e Administrator/in das Konto deaktiviert.", + "lead": "In jedem Fall ist die einzige Möglichkeit, ein deaktiviertes Konto wieder zu aktivieren, den Support zu kontaktieren.", + "closing": "Um den Support zu kontaktieren, kannst du auf diese E-Mail antworten." +} diff --git a/sites/backend/src/templates/email/signup-aed/de.yaml b/sites/backend/src/templates/email/signup-aed/de.yaml deleted file mode 100644 index a715e393b8e..00000000000 --- a/sites/backend/src/templates/email/signup-aed/de.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Dein Konto ist als deaktiviert markiert' -heading: Dein FreeSewing-Konto ist deaktiviert -preLead: 'Ein Konto kann deaktiviert werden, wenn ein/e Nutzer/in seine/ihre Zustimmung widerruft oder (in Ausnahmefällen) wenn ein/e Administrator/in das Konto deaktiviert.' -lead: 'In jedem Fall ist die einzige Möglichkeit, ein deaktiviertes Konto wieder zu aktivieren, den Support zu kontaktieren.' -closing: 'Um den Support zu kontaktieren, kannst du auf diese E-Mail antworten.' diff --git a/sites/backend/src/templates/email/signup-aed/en.json b/sites/backend/src/templates/email/signup-aed/en.json new file mode 100644 index 00000000000..9443471dbce --- /dev/null +++ b/sites/backend/src/templates/email/signup-aed/en.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Your account is marked as disabled", + "heading": "Your FreeSewing account is disabled", + "preLead": "An account can become disabled when a user revokes consent, or (exceptionally) when an administrator disables it.", + "lead": "In any case, the only way to re-enable a disabled account is to reach out to support.", + "closing": "To contact support, you can reply to this email." +} diff --git a/sites/backend/src/templates/email/signup-aed/en.yaml b/sites/backend/src/templates/email/signup-aed/en.yaml deleted file mode 100644 index 1348808394a..00000000000 --- a/sites/backend/src/templates/email/signup-aed/en.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Your account is marked as disabled' -heading: Your FreeSewing account is disabled -preLead: 'An account can become disabled when a user revokes consent, or (exceptionally) when an administrator disables it.' -lead: 'In any case, the only way to re-enable a disabled account is to reach out to support.' -closing: 'To contact support, you can reply to this email.' diff --git a/sites/backend/src/templates/email/signup-aed/es.json b/sites/backend/src/templates/email/signup-aed/es.json new file mode 100644 index 00000000000..5be9f6617b6 --- /dev/null +++ b/sites/backend/src/templates/email/signup-aed/es.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Tu cuenta está marcada como desactivada", + "heading": "Tu cuenta de FreeSewing está desactivada", + "preLead": "Una cuenta puede desactivarse cuando un usuario revoca su consentimiento, o (excepcionalmente) cuando un administrador la desactiva.", + "lead": "En cualquier caso, la única forma de volver a activar una cuenta desactivada es ponerse en contacto con el servicio de asistencia.", + "closing": "Para ponerte en contacto con el servicio de asistencia, puedes responder a este correo electrónico." +} diff --git a/sites/backend/src/templates/email/signup-aed/es.yaml b/sites/backend/src/templates/email/signup-aed/es.yaml deleted file mode 100644 index 0b94cfd32ea..00000000000 --- a/sites/backend/src/templates/email/signup-aed/es.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Tu cuenta está marcada como desactivada' -heading: Tu cuenta de FreeSewing está desactivada -preLead: 'Una cuenta puede desactivarse cuando un usuario revoca su consentimiento, o (excepcionalmente) cuando un administrador la desactiva.' -lead: 'En cualquier caso, la única forma de volver a activar una cuenta desactivada es ponerse en contacto con el servicio de asistencia.' -closing: 'Para ponerte en contacto con el servicio de asistencia, puedes responder a este correo electrónico.' diff --git a/sites/backend/src/templates/email/signup-aed/fr.json b/sites/backend/src/templates/email/signup-aed/fr.json new file mode 100644 index 00000000000..d8640bafd6d --- /dev/null +++ b/sites/backend/src/templates/email/signup-aed/fr.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Ton compte est marqué comme désactivé", + "heading": "Ton compte FreeSewing est désactivé", + "preLead": "Un compte peut être désactivé lorsqu'un utilisateur révoque son consentement ou (exceptionnellement) lorsqu'un administrateur le désactive.", + "lead": "Dans tous les cas, la seule façon de réactiver un compte désactivé est de tendre la main à l'assistance.", + "closing": "Pour contacter l'assistance, tu peux répondre à cet e-mail." +} diff --git a/sites/backend/src/templates/email/signup-aed/fr.yaml b/sites/backend/src/templates/email/signup-aed/fr.yaml deleted file mode 100644 index 9b0ee3c0274..00000000000 --- a/sites/backend/src/templates/email/signup-aed/fr.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Ton compte est marqué comme désactivé' -heading: Ton compte FreeSewing est désactivé -preLead: 'Un compte peut être désactivé lorsqu''un utilisateur révoque son consentement ou (exceptionnellement) lorsqu''un administrateur le désactive.' -lead: 'Dans tous les cas, la seule façon de réactiver un compte désactivé est de tendre la main à l''assistance.' -closing: 'Pour contacter l''assistance, tu peux répondre à cet e-mail.' diff --git a/sites/backend/src/templates/email/signup-aed/index.mjs b/sites/backend/src/templates/email/signup-aed/index.mjs index 9921668c794..e9d0f781ce1 100644 --- a/sites/backend/src/templates/email/signup-aed/index.mjs +++ b/sites/backend/src/templates/email/signup-aed/index.mjs @@ -1,10 +1,11 @@ import { closingRow, headingRow, preLeadRow, wrap } from '../shared/blocks.mjs' // Translations -import en from '../../../../public/locales/en/signup-aed.json' assert { type: 'json' } -import de from '../../../../public/locales/de/signup-aed.json' assert { type: 'json' } -import es from '../../../../public/locales/es/signup-aed.json' assert { type: 'json' } -import fr from '../../../../public/locales/fr/signup-aed.json' assert { type: 'json' } -import nl from '../../../../public/locales/nl/signup-aed.json' assert { type: 'json' } +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } // aed = Account Exists but is Disabled export const signupaed = { @@ -20,4 +21,4 @@ ${closingRow.text} `), } -export const translations = { en, de, es, fr, nl } +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/signup-aed/nl.json b/sites/backend/src/templates/email/signup-aed/nl.json new file mode 100644 index 00000000000..8ef0140b44c --- /dev/null +++ b/sites/backend/src/templates/email/signup-aed/nl.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Je account is gemarkeerd als uitgeschakeld", + "heading": "Je FreeSewing account is uitgeschakeld", + "preLead": "Een account kan worden uitgeschakeld wanneer een gebruiker zijn toestemming intrekt, of (uitzonderlijk) wanneer een beheerder het uitschakelt.", + "lead": "Hoe dan ook, de enige manier om een uitgeschakeld account weer in te schakelen is door contact op te nemen met support.", + "closing": "Om contact op te nemen met ondersteuning, kun je deze e-mail beantwoorden." +} diff --git a/sites/backend/src/templates/email/signup-aed/nl.yaml b/sites/backend/src/templates/email/signup-aed/nl.yaml deleted file mode 100644 index 4bb4091348d..00000000000 --- a/sites/backend/src/templates/email/signup-aed/nl.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Je account is gemarkeerd als uitgeschakeld' -heading: Je FreeSewing account is uitgeschakeld -preLead: 'Een account kan worden uitgeschakeld wanneer een gebruiker zijn toestemming intrekt, of (uitzonderlijk) wanneer een beheerder het uitschakelt.' -lead: 'Hoe dan ook, de enige manier om een uitgeschakeld account weer in te schakelen is door contact op te nemen met support.' -closing: 'Om contact op te nemen met ondersteuning, kun je deze e-mail beantwoorden.' diff --git a/sites/backend/src/templates/email/signup-aed/uk.json b/sites/backend/src/templates/email/signup-aed/uk.json new file mode 100644 index 00000000000..a498a4da068 --- /dev/null +++ b/sites/backend/src/templates/email/signup-aed/uk.json @@ -0,0 +1,7 @@ +{ + "subject": "[FreeSewing] Ваш обліковий запис позначено як вимкнений", + "heading": "Ваш обліковий запис FreeSewing вимкнено", + "preLead": "Обліковий запис може бути відключений, коли користувач відкликає свою згоду, або (у виняткових випадках) коли його відключає адміністратор.", + "lead": "У будь-якому випадку, єдиний спосіб відновити дію вимкненого акаунта - звернутися до служби підтримки.", + "closing": "Щоб зв'язатися зі службою підтримки, ви можете відповісти на цей лист." +} diff --git a/sites/backend/src/templates/email/signup-aed/uk.yaml b/sites/backend/src/templates/email/signup-aed/uk.yaml deleted file mode 100644 index b68a9ff0c60..00000000000 --- a/sites/backend/src/templates/email/signup-aed/uk.yaml +++ /dev/null @@ -1,5 +0,0 @@ -subject: '[FreeSewing] Ваш обліковий запис позначено як вимкнений' -heading: Ваш обліковий запис FreeSewing вимкнено -preLead: 'Обліковий запис може бути відключений, коли користувач відкликає свою згоду, або (у виняткових випадках) коли його відключає адміністратор.' -lead: 'У будь-якому випадку, єдиний спосіб відновити дію вимкненого акаунта - звернутися до служби підтримки.' -closing: 'Щоб зв''язатися зі службою підтримки, ви можете відповісти на цей лист.' diff --git a/sites/backend/src/templates/email/signup/de.json b/sites/backend/src/templates/email/signup/de.json new file mode 100644 index 00000000000..bff8a65de0b --- /dev/null +++ b/sites/backend/src/templates/email/signup/de.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Hier ist dein Anmeldelink für FreeSewing.org", + "heading": "FreeSewing beitreten", + "lead": "Um ein FreeSewing-Konto zu erstellen, das mit dieser E-Mail-Adresse verknüpft ist, klicke auf das große schwarze Rechteck unten:", + "text-lead": "Um ein FreeSewing-Konto zu erstellen, das mit dieser E-Mail-Adresse verknüpft ist, klicke auf den Link unten:", + "button": "Ein Konto erstellen", + "closing": "Das ist alles für den Moment." +} diff --git a/sites/backend/src/templates/email/signup/de.yaml b/sites/backend/src/templates/email/signup/de.yaml deleted file mode 100644 index 943a7b7120b..00000000000 --- a/sites/backend/src/templates/email/signup/de.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Hier ist dein Anmeldelink für FreeSewing.org" -heading: FreeSewing beitreten -lead: 'Um ein FreeSewing-Konto zu erstellen, das mit dieser E-Mail-Adresse verknüpft ist, klicke auf das große schwarze Rechteck unten:' -text-lead: 'Um ein FreeSewing-Konto zu erstellen, das mit dieser E-Mail-Adresse verknüpft ist, klicke auf den Link unten:' -button: Ein Konto erstellen -closing: "Das ist alles für den Moment." diff --git a/sites/backend/src/templates/email/signup/en.json b/sites/backend/src/templates/email/signup/en.json new file mode 100644 index 00000000000..b6bb96f322f --- /dev/null +++ b/sites/backend/src/templates/email/signup/en.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Here is your sign-up link for FreeSewing.org", + "heading": "Join FreeSewing", + "lead": "To create a FreeSewing account linked to this email address, click the big black rectangle below:", + "text-lead": "To create a FreeSewing account linked to this email address, click the link below:", + "button": "Create an account", + "closing": "That's all for now." +} diff --git a/sites/backend/src/templates/email/signup/en.yaml b/sites/backend/src/templates/email/signup/en.yaml deleted file mode 100644 index da9da542e51..00000000000 --- a/sites/backend/src/templates/email/signup/en.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Here is your sign-up link for FreeSewing.org" -heading: Join FreeSewing -lead: 'To create a FreeSewing account linked to this email address, click the big black rectangle below:' -text-lead: 'To create a FreeSewing account linked to this email address, click the link below:' -button: Create an account -closing: "That's all for now." diff --git a/sites/backend/src/templates/email/signup/es.json b/sites/backend/src/templates/email/signup/es.json new file mode 100644 index 00000000000..aadb316a368 --- /dev/null +++ b/sites/backend/src/templates/email/signup/es.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Aquí tienes el enlace para inscribirte en FreeSewing.org", + "heading": "Únete a FreeSewing", + "lead": "Para crear una cuenta FreeSewing vinculada a esta dirección de correo electrónico, haz clic en el rectángulo negro grande de abajo:", + "text-lead": "Para crear una cuenta FreeSewing vinculada a esta dirección de correo electrónico, haz clic en el siguiente enlace:", + "button": "Crear una cuenta", + "closing": "Eso es todo por ahora." +} diff --git a/sites/backend/src/templates/email/signup/es.yaml b/sites/backend/src/templates/email/signup/es.yaml deleted file mode 100644 index fdb8b8c7f24..00000000000 --- a/sites/backend/src/templates/email/signup/es.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Aquí tienes el enlace para inscribirte en FreeSewing.org" -heading: Únete a FreeSewing -lead: 'Para crear una cuenta FreeSewing vinculada a esta dirección de correo electrónico, haz clic en el rectángulo negro grande de abajo:' -text-lead: 'Para crear una cuenta FreeSewing vinculada a esta dirección de correo electrónico, haz clic en el siguiente enlace:' -button: Crear una cuenta -closing: "Eso es todo por ahora." diff --git a/sites/backend/src/templates/email/signup/fr.json b/sites/backend/src/templates/email/signup/fr.json new file mode 100644 index 00000000000..08e1b625a66 --- /dev/null +++ b/sites/backend/src/templates/email/signup/fr.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Voici ton lien d'inscription à FreeSewing.org", + "heading": "Rejoignez FreeSewing", + "lead": "Pour créer un compte FreeSewing lié à cette adresse email, clique sur le grand rectangle noir ci-dessous :", + "text-lead": "Pour créer un compte FreeSewing lié à cette adresse e-mail, clique sur le lien ci-dessous :", + "button": "Créer un compte", + "closing": "C'est tout pour l'instant." +} diff --git a/sites/backend/src/templates/email/signup/fr.yaml b/sites/backend/src/templates/email/signup/fr.yaml deleted file mode 100644 index de8a5a69b7f..00000000000 --- a/sites/backend/src/templates/email/signup/fr.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Voici ton lien d'inscription à FreeSewing.org" -heading: Rejoignez FreeSewing -lead: 'Pour créer un compte FreeSewing lié à cette adresse email, clique sur le grand rectangle noir ci-dessous :' -text-lead: 'Pour créer un compte FreeSewing lié à cette adresse e-mail, clique sur le lien ci-dessous :' -button: Créer un compte -closing: "C'est tout pour l'instant." diff --git a/sites/backend/src/templates/email/signup/index.mjs b/sites/backend/src/templates/email/signup/index.mjs index 43a7a2801c4..1b09841763f 100644 --- a/sites/backend/src/templates/email/signup/index.mjs +++ b/sites/backend/src/templates/email/signup/index.mjs @@ -1,10 +1,11 @@ import { buttonRow, closingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs' // Translations -import en from '../../../../public/locales/en/signup.json' assert { type: 'json' } -import de from '../../../../public/locales/de/signup.json' assert { type: 'json' } -import es from '../../../../public/locales/es/signup.json' assert { type: 'json' } -import fr from '../../../../public/locales/fr/signup.json' assert { type: 'json' } -import nl from '../../../../public/locales/nl/signup.json' assert { type: 'json' } +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } export const signup = { html: wrap.html(` @@ -29,4 +30,4 @@ PS: {{{ text-ps }}} : {{{ supportUrl }}} `), } -export const translations = { en, de, es, fr, nl } +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/signup/nl.json b/sites/backend/src/templates/email/signup/nl.json new file mode 100644 index 00000000000..975c175b867 --- /dev/null +++ b/sites/backend/src/templates/email/signup/nl.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Hier is je aanmeldlink voor FreeSewing.org", + "heading": "Word lid van FreeSewing", + "lead": "Klik op de grote zwarte rechthoek hieronder om een FreeSewing account aan dit e-mailadres te koppelen:", + "text-lead": "Klik op de onderstaande link om een FreeSewing account te maken dat is gekoppeld aan dit e-mailadres:", + "button": "Maak een account aan", + "closing": "Dat is alles voor nu." +} diff --git a/sites/backend/src/templates/email/signup/nl.yaml b/sites/backend/src/templates/email/signup/nl.yaml deleted file mode 100644 index 9d4e38d3482..00000000000 --- a/sites/backend/src/templates/email/signup/nl.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Hier is je aanmeldlink voor FreeSewing.org" -heading: Word lid van FreeSewing -lead: 'Klik op de grote zwarte rechthoek hieronder om een FreeSewing account aan dit e-mailadres te koppelen:' -text-lead: 'Klik op de onderstaande link om een FreeSewing account te maken dat is gekoppeld aan dit e-mailadres:' -button: Maak een account aan -closing: "Dat is alles voor nu." diff --git a/sites/backend/src/templates/email/signup/uk.json b/sites/backend/src/templates/email/signup/uk.json new file mode 100644 index 00000000000..ceaeaa5f9f0 --- /dev/null +++ b/sites/backend/src/templates/email/signup/uk.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Ось ваше посилання для реєстрації на FreeSewing.org", + "heading": "Приєднатися до FreeSewing", + "lead": "Щоб створити обліковий запис FreeSewing, пов'язаний з цією адресою електронної пошти, натисніть великий чорний прямокутник нижче:", + "text-lead": "Щоб створити обліковий запис FreeSewing, пов'язаний з цією електронною адресою, натисніть на посилання нижче:", + "button": "Створіть обліковий запис", + "closing": "Наразі це все." +} diff --git a/sites/backend/src/templates/email/signup/uk.yaml b/sites/backend/src/templates/email/signup/uk.yaml deleted file mode 100644 index 2c930cbddf4..00000000000 --- a/sites/backend/src/templates/email/signup/uk.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Ось ваше посилання для реєстрації на FreeSewing.org" -heading: Приєднатися до FreeSewing -lead: 'Щоб створити обліковий запис FreeSewing, пов''язаний з цією адресою електронної пошти, натисніть великий чорний прямокутник нижче:' -text-lead: 'Щоб створити обліковий запис FreeSewing, пов''язаний з цією електронною адресою, натисніть на посилання нижче:' -button: Створіть обліковий запис -closing: "Наразі це все." diff --git a/sites/backend/src/templates/email/transinvite/de.json b/sites/backend/src/templates/email/transinvite/de.json new file mode 100644 index 00000000000..ed62f0d0a44 --- /dev/null +++ b/sites/backend/src/templates/email/transinvite/de.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Deine Einladung, dem FreeSewing-Übersetzungsteam beizutreten", + "heading": "Trete einem FreeSewing-Übersetzungsteam bei", + "lead": "Um dem FreeSewing-Übersetzungsteam beizutreten, klicke auf das große schwarze Rechteck unten:", + "text-lead": "Um dem FreeSewing-Übersetzungsteam beizutreten, klicke auf den untenstehenden Link:", + "button": "Trete dem Übersetzungsteam bei", + "closing": "So kommst du zu Crowdin, der von uns genutzten Übersetzungsplattform." +} diff --git a/sites/backend/src/templates/email/transinvite/de.yaml b/sites/backend/src/templates/email/transinvite/de.yaml deleted file mode 100644 index 0790fd41ac0..00000000000 --- a/sites/backend/src/templates/email/transinvite/de.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Deine Einladung, dem FreeSewing-Übersetzungsteam beizutreten" -heading: Trete einem FreeSewing-Übersetzungsteam bei -lead: 'Um dem FreeSewing-Übersetzungsteam beizutreten, klicke auf das große schwarze Rechteck unten:' -text-lead: 'Um dem FreeSewing-Übersetzungsteam beizutreten, klicke auf den untenstehenden Link:' -button: Trete dem Übersetzungsteam bei -closing: "So kommst du zu Crowdin, der von uns genutzten Übersetzungsplattform." diff --git a/sites/backend/src/templates/email/transinvite/en.json b/sites/backend/src/templates/email/transinvite/en.json new file mode 100644 index 00000000000..8514b51bf3b --- /dev/null +++ b/sites/backend/src/templates/email/transinvite/en.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Your invitation to join FreeSewing's the translation team", + "heading": "Join a FreeSewing translation team", + "lead": "To join the FreeSewing translation team, click the big black rectangle below:", + "text-lead": "To join the FreeSewing translation team, click the link below:", + "button": "Join the translation team", + "closing": "This will take you to Crowdin, the translation platform we use." +} diff --git a/sites/backend/src/templates/email/transinvite/en.yaml b/sites/backend/src/templates/email/transinvite/en.yaml deleted file mode 100644 index 08af7f8536d..00000000000 --- a/sites/backend/src/templates/email/transinvite/en.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Your invitation to join FreeSewing's the translation team" -heading: Join a FreeSewing translation team -lead: 'To join the FreeSewing translation team, click the big black rectangle below:' -text-lead: 'To join the FreeSewing translation team, click the link below:' -button: Join the translation team -closing: "This will take you to Crowdin, the translation platform we use." diff --git a/sites/backend/src/templates/email/transinvite/es.json b/sites/backend/src/templates/email/transinvite/es.json new file mode 100644 index 00000000000..70ba9986337 --- /dev/null +++ b/sites/backend/src/templates/email/transinvite/es.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Tu invitación para unirte al equipo de traducción de FreeSewing", + "heading": "Únete a un equipo de traducción de FreeSewing", + "lead": "Para unirte al equipo de traducción de FreeSewing, haz clic en el rectángulo negro grande de abajo:", + "text-lead": "Para unirte al equipo de traducción de FreeSewing, haz clic en el siguiente enlace:", + "button": "Únete al equipo de traducción", + "closing": "Esto te llevará a Crowdin, la plataforma de traducción que utilizamos." +} diff --git a/sites/backend/src/templates/email/transinvite/es.yaml b/sites/backend/src/templates/email/transinvite/es.yaml deleted file mode 100644 index 33a62412605..00000000000 --- a/sites/backend/src/templates/email/transinvite/es.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Tu invitación para unirte al equipo de traducción de FreeSewing" -heading: Únete a un equipo de traducción de FreeSewing -lead: 'Para unirte al equipo de traducción de FreeSewing, haz clic en el rectángulo negro grande de abajo:' -text-lead: 'Para unirte al equipo de traducción de FreeSewing, haz clic en el siguiente enlace:' -button: Únete al equipo de traducción -closing: "Esto te llevará a Crowdin, la plataforma de traducción que utilizamos." diff --git a/sites/backend/src/templates/email/transinvite/fr.json b/sites/backend/src/templates/email/transinvite/fr.json new file mode 100644 index 00000000000..a1faa163102 --- /dev/null +++ b/sites/backend/src/templates/email/transinvite/fr.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Ton invitation à rejoindre l'équipe de traduction de FreeSewing", + "heading": "Rejoins une équipe de traduction FreeSewing", + "lead": "Pour rejoindre l''équipe de traduction de FreeSewing, clique sur le grand rectangle noir ci-dessous :", + "text-lead": "Pour rejoindre l''équipe de traduction de FreeSewing, clique sur le lien ci-dessous :", + "button": "Rejoins l'équipe de traduction", + "closing": "Cela te mènera à Crowdin, la plateforme de traduction que nous utilisons." +} diff --git a/sites/backend/src/templates/email/transinvite/fr.yaml b/sites/backend/src/templates/email/transinvite/fr.yaml deleted file mode 100644 index f306c1c1bcd..00000000000 --- a/sites/backend/src/templates/email/transinvite/fr.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Ton invitation à rejoindre l'équipe de traduction de FreeSewing" -heading: Rejoins une équipe de traduction FreeSewing -lead: 'Pour rejoindre l''équipe de traduction de FreeSewing, clique sur le grand rectangle noir ci-dessous :' -text-lead: 'Pour rejoindre l''équipe de traduction de FreeSewing, clique sur le lien ci-dessous :' -button: Rejoins l'équipe de traduction -closing: "Cela te mènera à Crowdin, la plateforme de traduction que nous utilisons." diff --git a/sites/backend/src/templates/email/transinvite/index.mjs b/sites/backend/src/templates/email/transinvite/index.mjs index 7c42889e504..c43c823af8b 100644 --- a/sites/backend/src/templates/email/transinvite/index.mjs +++ b/sites/backend/src/templates/email/transinvite/index.mjs @@ -1,10 +1,11 @@ import { buttonRow, closingRow, headingRow, lead1Row, wrap } from '../shared/blocks.mjs' // Translations -import en from '../../../../public/locales/en/transinvite.json' assert { type: 'json' } -import de from '../../../../public/locales/de/transinvite.json' assert { type: 'json' } -import es from '../../../../public/locales/es/transinvite.json' assert { type: 'json' } -import fr from '../../../../public/locales/fr/transinvite.json' assert { type: 'json' } -import nl from '../../../../public/locales/nl/transinvite.json' assert { type: 'json' } +import en from './en.json' assert { type: 'json' } +import de from './de.json' assert { type: 'json' } +import es from './es.json' assert { type: 'json' } +import fr from './fr.json' assert { type: 'json' } +import nl from './nl.json' assert { type: 'json' } +import uk from './uk.json' assert { type: 'json' } export const transinvite = { html: wrap.html(` @@ -29,4 +30,4 @@ PS: {{{ text-ps }}} : {{{ supportUrl }}} `), } -export const translations = { en, de, es, fr, nl } +export const translations = { en, de, es, fr, nl, uk } diff --git a/sites/backend/src/templates/email/transinvite/nl.json b/sites/backend/src/templates/email/transinvite/nl.json new file mode 100644 index 00000000000..9eabfaad43c --- /dev/null +++ b/sites/backend/src/templates/email/transinvite/nl.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Je uitnodiging om deel te nemen aan het vertaalteam van FreeSewing", + "heading": "Word lid van een FreeSewing vertaalteam", + "lead": "Klik op de grote zwarte rechthoek hieronder om lid te worden van het vertaalteam van FreeSewing:", + "text-lead": "Klik op de onderstaande link om lid te worden van het vertaalteam van FreeSewing:", + "button": "Word lid van het vertaalteam", + "closing": "Dit brengt je naar Crowdin, het vertaalplatform dat we gebruiken." +} diff --git a/sites/backend/src/templates/email/transinvite/nl.yaml b/sites/backend/src/templates/email/transinvite/nl.yaml deleted file mode 100644 index a88364029c1..00000000000 --- a/sites/backend/src/templates/email/transinvite/nl.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Je uitnodiging om deel te nemen aan het vertaalteam van FreeSewing" -heading: Word lid van een FreeSewing vertaalteam -lead: 'Klik op de grote zwarte rechthoek hieronder om lid te worden van het vertaalteam van FreeSewing:' -text-lead: 'Klik op de onderstaande link om lid te worden van het vertaalteam van FreeSewing:' -button: Word lid van het vertaalteam -closing: "Dit brengt je naar Crowdin, het vertaalplatform dat we gebruiken." diff --git a/sites/backend/src/templates/email/transinvite/uk.json b/sites/backend/src/templates/email/transinvite/uk.json new file mode 100644 index 00000000000..5fd2a86313c --- /dev/null +++ b/sites/backend/src/templates/email/transinvite/uk.json @@ -0,0 +1,8 @@ +{ + "subject": "[FreeSewing] Ваше запрошення приєднатися до команди перекладачів FreeSewing", + "heading": "Приєднуйтесь до команди перекладачів FreeSewing", + "lead": "Щоб приєднатися до команди перекладачів FreeSewing, натисніть великий чорний прямокутник нижче:", + "text-lead": "Щоб приєднатися до команди перекладачів FreeSewing, натисніть на посилання нижче:", + "button": "Приєднуйтесь до команди перекладачів", + "closing": "Ви потрапите на Crowdin, платформу для перекладу, яку ми використовуємо." +} diff --git a/sites/backend/src/templates/email/transinvite/uk.yaml b/sites/backend/src/templates/email/transinvite/uk.yaml deleted file mode 100644 index 892cfc20749..00000000000 --- a/sites/backend/src/templates/email/transinvite/uk.yaml +++ /dev/null @@ -1,6 +0,0 @@ -subject: "[FreeSewing] Ваше запрошення приєднатися до команди перекладачів FreeSewing" -heading: Приєднуйтесь до команди перекладачів FreeSewing -lead: 'Щоб приєднатися до команди перекладачів FreeSewing, натисніть великий чорний прямокутник нижче:' -text-lead: 'Щоб приєднатися до команди перекладачів FreeSewing, натисніть на посилання нижче:' -button: Приєднуйтесь до команди перекладачів -closing: "Ви потрапите на Crowdin, платформу для перекладу, яку ми використовуємо." diff --git a/sites/backend/src/templates/email/uk.json b/sites/backend/src/templates/email/uk.json new file mode 100644 index 00000000000..fabf381f4c8 --- /dev/null +++ b/sites/backend/src/templates/email/uk.json @@ -0,0 +1,10 @@ +{ + "greeting": "з любов'ю", + "ps-pre-link": "FreeSewing безкоштовний, але, будь ласка", + "ps-link": "стати патроном", + "ps-post-link": "якщо можеш собі це дозволити.", + "text-ps": "FreeSewing є безкоштовним, але, будь ласка, станьте меценатом, якщо ви можете собі це дозволити.", + "notMarketing": "Це не маркетинговий, а транзакційний лист про ваш обліковий запис FreeSewing.", + "seeWhy": "Для отримання додаткової інформації див:", + "whyDidIGetThis": "Чому я отримав цей лист?" +} diff --git a/sites/backend/src/templates/email/uk.yaml b/sites/backend/src/templates/email/uk.yaml deleted file mode 100644 index 1f72815b64f..00000000000 --- a/sites/backend/src/templates/email/uk.yaml +++ /dev/null @@ -1,9 +0,0 @@ -#Shared -greeting: з любов'ю -ps-pre-link: FreeSewing безкоштовний, але, будь ласка -ps-link: стати патроном -ps-post-link: якщо можеш собі це дозволити. -text-ps: 'FreeSewing є безкоштовним, але, будь ласка, станьте меценатом, якщо ви можете собі це дозволити.' -notMarketing: Це не маркетинговий, а транзакційний лист про ваш обліковий запис FreeSewing. -seeWhy: 'Для отримання додаткової інформації див:' -whyDidIGetThis: Чому я отримав цей лист? diff --git a/sites/backend/src/utils/email.mjs b/sites/backend/src/utils/email.mjs index c3c957fcfaf..f4f1f67dc88 100644 --- a/sites/backend/src/utils/email.mjs +++ b/sites/backend/src/utils/email.mjs @@ -2,6 +2,7 @@ import { templates, translations } from '../templates/email/index.mjs' import { SESv2Client, SendEmailCommand } from '@aws-sdk/client-sesv2' import mustache from 'mustache' import { log } from './log.mjs' +console.log(Object.keys(templates)) /* * Exporting this closure that makes sure we have access to the @@ -25,7 +26,8 @@ async function sendEmailViaAwsSes( ) { // Make sure we have what it takes if (!template || !to || typeof templates[template] === 'undefined') { - log.warn(`Tried to email invalid template: ${template}`) + if (!to) log.warn(`A To: address is mandatory when sending email`) + else log.warn(`Tried to email invalid template: ${template}`) return false } diff --git a/sites/backend/tests/index.mjs b/sites/backend/tests/index.mjs index a2e3f1bff98..eb37459baab 100644 --- a/sites/backend/tests/index.mjs +++ b/sites/backend/tests/index.mjs @@ -5,16 +5,18 @@ import { apikeyTests } from './apikey.mjs' import { setTests } from './set.mjs' import { curatedSetTests } from './curated-set.mjs' import { patternTests } from './pattern.mjs' +import { subscriberTests } from './subscriber.mjs' import { setup } from './shared.mjs' const runTests = async (...params) => { - await userTests(...params) - await mfaTests(...params) - await apikeyTests(...params) - await accountTests(...params) - await setTests(...params) - await curatedSetTests(...params) - await patternTests(...params) + //await userTests(...params) + //await mfaTests(...params) + //await apikeyTests(...params) + //await accountTests(...params) + //await setTests(...params) + //await curatedSetTests(...params) + //await patternTests(...params) + await subscriberTests(...params) } // Load initial data required for tests diff --git a/sites/backend/tests/shared.mjs b/sites/backend/tests/shared.mjs index 6277ad4a94c..c16c3ee9569 100644 --- a/sites/backend/tests/shared.mjs +++ b/sites/backend/tests/shared.mjs @@ -41,6 +41,7 @@ export const setup = async () => { key: '🎟️ ', set: '🧕 ', pattern: '👕 ', + subscriber: '📬', }, randomString, } diff --git a/sites/backend/tests/subscriber.mjs b/sites/backend/tests/subscriber.mjs new file mode 100644 index 00000000000..0c9232f4744 --- /dev/null +++ b/sites/backend/tests/subscriber.mjs @@ -0,0 +1,92 @@ +export const subscriberTests = async (chai, config, expect, store) => { + describe(`${store.icon('subscriber')} Subscriber tests`, () => { + it(`${store.icon('subscriber')} Should not subscribe without an email address`, (done) => { + const data = { + language: 'nL', + test: 'yes please', + } + chai + .request(config.api) + .post(`/subscriber`) + .send(data) + .end((err, res) => { + expect(err === null).to.equal(true) + expect(res.status).to.equal(400) + expect(res.body.result).to.equal('error') + expect(res.body.error).to.equal('emailMissing') + done() + }) + }) + + it(`${store.icon('subscriber')} Should not subscribe without a language`, (done) => { + const data = { + email: 'joost@FREESEWING.dev', + test: 'yes please', + } + chai + .request(config.api) + .post(`/subscriber`) + .send(data) + .end((err, res) => { + expect(err === null).to.equal(true) + expect(res.status).to.equal(400) + expect(res.body.result).to.equal('error') + expect(res.body.error).to.equal('languageMissing') + done() + }) + }) + + it(`${store.icon('subscriber')} Should subscribe`, (done) => { + const data = { + email: 'joost@FREESEWING.dev', + language: 'eN', + test: 'yes please', + } + chai + .request(config.api) + .post(`/subscriber`) + .send(data) + .end((err, res) => { + expect(err === null).to.equal(true) + expect(res.status).to.equal(200) + expect(res.body.result).to.equal('success') + expect(res.body.data.email).to.equal(data.email.toLowerCase()) + expect(res.body.data.language).to.equal(data.language.toLowerCase()) + expect(typeof res.body.data.id).to.equal('string') + expect(typeof res.body.data.ehash).to.equal('string') + store.subscriber = res.body.data + done() + }) + }) + + it(`${store.icon('subscriber')} Should confirm a subscription`, (done) => { + chai + .request(config.api) + .put(`/subscriber`) + .send({ + id: store.subscriber.id, + ehash: store.subscriber.ehash, + }) + .end((err, res) => { + expect(err === null).to.equal(true) + expect(res.status).to.equal(200) + done() + }) + }) + + //it(`${store.icon('subscriber')} Should unsubscribe`, (done) => { + // chai + // .request(config.api) + // .delete(`/subscriber`) + // .send({ + // id: store.subscriber.id, + // ehash: store.subscriber.ehash, + // }) + // .end((err, res) => { + // expect(err === null).to.equal(true) + // expect(res.status).to.equal(200) + // done() + // }) + //}) + }) +} diff --git a/sites/org/pages/newsletter/index.mjs b/sites/org/pages/newsletter/index.mjs new file mode 100644 index 00000000000..9cd3289a9b8 --- /dev/null +++ b/sites/org/pages/newsletter/index.mjs @@ -0,0 +1,43 @@ +// Dependencies +import { serverSideTranslations } from 'next-i18next/serverSideTranslations' +import { nsMerge } from 'shared/utils.mjs' +// Hooks +import { useTranslation } from 'next-i18next' +// Components +import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' +import { Popout } from 'shared/components/popout/index.mjs' + +// Translation namespaces used on this page +const namespaces = nsMerge(pageNs, 'newsletter') + +/* + * Each page MUST be wrapped in the PageWrapper component. + * You also MUST spread props.page into this wrapper component + * when path and locale come from static props (as here) + * or set them manually. + */ +const NewsletterPage = ({ page }) => { + const { t } = useTranslation(namespaces) + + return ( + +
+ handle newsletter subscription here +
+
+ ) +} + +export default NewsletterPage + +export async function getStaticProps({ locale }) { + return { + props: { + ...(await serverSideTranslations(locale, namespaces)), + page: { + locale, + path: ['newsletter'], + }, + }, + } +} diff --git a/sites/org/pages/newsletter/subscribe/[...tokens].mjs b/sites/org/pages/newsletter/subscribe/[...tokens].mjs new file mode 100644 index 00000000000..9939e8e4968 --- /dev/null +++ b/sites/org/pages/newsletter/subscribe/[...tokens].mjs @@ -0,0 +1,107 @@ +// Dependencies +import { serverSideTranslations } from 'next-i18next/serverSideTranslations' +import { nsMerge } from 'shared/utils.mjs' +// Hooks +import { useState, useContext } from 'react' +import { useTranslation } from 'next-i18next' +import { useBackend } from 'shared/hooks/use-backend.mjs' +// Context +import { LoadingContext } from 'shared/context/loading-context.mjs' +// Components +import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' +import { Popout } from 'shared/components/popout/index.mjs' +import { PageLink } from 'shared/components/page-link.mjs' + +// Translation namespaces used on this page +const namespaces = nsMerge(pageNs, 'newsletter') + +/* + * Each page MUST be wrapped in the PageWrapper component. + * You also MUST spread props.page into this wrapper component + * when path and locale come from static props (as here) + * or set them manually. + */ +const NewsletterPage = ({ page, id, ehash }) => { + const { t } = useTranslation(namespaces) + const { loading, setLoading } = useContext(LoadingContext) + const backend = useBackend() + + const [confirmed, setConfirmed] = useState(false) + + const handler = async () => { + setLoading(true) + const result = await backend.confirmNewsletterSubscribe({ id, ehash }) + setLoading(false) + setConfirmed(true) + } + + return ( + +
+ {confirmed ? ( + <> +

{t('newsletter:newsletter')}

+

{t('newsletter:thanksDone')}

+ +

{t('newsletter:subscribePs')}

+

+ +

+
+ + ) : ( + <> +

+ {t('newsletter:newsletter')}: {t('newsletter:subscribe')} +

+
{t('newsletter:subscribeConfirm')}
+

{t('newsletter:subscribeLead')}

+ + +
{t('newsletter:whatsWithTheClicks')}
+

{t('newsletter:whyLead')}

+

+ {t('newsletter:faqLead')}:{' '} + +

+
+ + )} +
+
+ ) +} + +export default NewsletterPage + +export async function getStaticProps({ locale, params }) { + return { + props: { + ...(await serverSideTranslations(locale, namespaces)), + id: params.tokens[0] || null, + ehash: params.tokens[1] || null, + page: { + locale, + path: ['newsletter'], + }, + }, + } +} + +/* + * Do not generate anything statically + */ +export async function getStaticPaths() { + return { + paths: [], + fallback: 'blocking', + } +} diff --git a/sites/org/pages/newsletter/unsubscribe/[...tokens].mjs b/sites/org/pages/newsletter/unsubscribe/[...tokens].mjs new file mode 100644 index 00000000000..beef8e76726 --- /dev/null +++ b/sites/org/pages/newsletter/unsubscribe/[...tokens].mjs @@ -0,0 +1,98 @@ +// Dependencies +import { serverSideTranslations } from 'next-i18next/serverSideTranslations' +import { nsMerge } from 'shared/utils.mjs' +// Hooks +import { useState, useContext } from 'react' +import { useTranslation } from 'next-i18next' +import { useBackend } from 'shared/hooks/use-backend.mjs' +// Context +import { LoadingContext } from 'shared/context/loading-context.mjs' +// Components +import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs' +import { Popout } from 'shared/components/popout/index.mjs' +import { PageLink } from 'shared/components/page-link.mjs' + +// Translation namespaces used on this page +const namespaces = nsMerge(pageNs, 'newsletter') + +/* + * Each page MUST be wrapped in the PageWrapper component. + * You also MUST spread props.page into this wrapper component + * when path and locale come from static props (as here) + * or set them manually. + */ +const NewsletterPage = ({ page, id, ehash }) => { + const { t } = useTranslation(namespaces) + const { loading, setLoading } = useContext(LoadingContext) + const backend = useBackend() + + const [confirmed, setConfirmed] = useState(false) + + const handler = async () => { + setLoading(true) + const result = await backend.confirmNewsletterUnsubscribe({ id, ehash }) + setLoading(false) + setConfirmed(true) + } + + return ( + +
+ {confirmed ? ( + <> +

{t('newsletter:newsletter')}

+

{t('newsletter:thanksDone')}

+ + ) : ( + <> +

+ {t('newsletter:newsletter')}: {t('newsletter:unsubscribe')} +

+
{t('newsletter:unsubscribeConfirm')}
+

{t('newsletter:unsubscribeLead')}

+ + +
{t('newsletter:whatsWithTheClicks')}
+

{t('newsletter:whyLead')}

+

+ {t('newsletter:faqLead')}:{' '} + +

+
+ + )} +
+
+ ) +} + +export default NewsletterPage + +export async function getStaticProps({ locale, params }) { + return { + props: { + ...(await serverSideTranslations(locale, namespaces)), + id: params.tokens[0] || null, + ehash: params.tokens[1] || null, + page: { + locale, + path: ['newsletter'], + }, + }, + } +} + +/* + * Do not generate anything statically + */ +export async function getStaticPaths() { + return { + paths: [], + fallback: 'blocking', + } +} diff --git a/sites/shared/components/newsletter/en.yaml b/sites/shared/components/newsletter/en.yaml new file mode 100644 index 00000000000..a2a0911ed2e --- /dev/null +++ b/sites/shared/components/newsletter/en.yaml @@ -0,0 +1,16 @@ +newsletter: Newsletter +subscribe: Subscribe +subscribeConfirm: Confirm you want to subscribe to the FreeSewing newsletter +subscribeLead: Once you click the button below, your subscription to the FreeSewing newsletter will be active. +subscribePs: You can unsubscribe at any time with the link below. This unsubscribe link will also be included at the bottom of every newsletter we send you, so you do not need to bookmark it, but you can if you want to. +subscribeWhy: Why do I have to click again to confirm I want to subscribe after I already clicked the confirmation link you sent me? +unsubscribeLink: Unsubscribe link +unsubscribe: Unsubscribe +unsubscribeConfirm: Confirm you want to unsubscribe from the FreeSewing newsletter +unsubscribeLead: Once you click the button below, you will be unsubscribed from the FreeSewing newsletter. +unsubscribeWhy: Why do I have to click again to confirm I want to unsubscribe after I already clicked the newsletter unsubscribe link? +whyLead: If you are curious why we are making you click yet another time, there is a good reason for that. +invalidLink: The link you followed to get here is invalid +faqLead: The answer is covered in our FAQ +whatsWithTheClicks: What's with all the clicks? +thanksDone: Thank you, that's all it took. diff --git a/sites/shared/hooks/use-backend.mjs b/sites/shared/hooks/use-backend.mjs index 63b8a67d970..0b097569172 100644 --- a/sites/shared/hooks/use-backend.mjs +++ b/sites/shared/hooks/use-backend.mjs @@ -302,10 +302,17 @@ Backend.prototype.sendLanguageSuggestion = async function (data) { } /* - * Create payment intent + * Confirm newsletter subscribe */ -Backend.prototype.createPaymentIntent = async function (data) { - return responseHandler(await api.post(`/payments/intent`, data), 201) +Backend.prototype.confirmNewsletterSubscribe = async function ({ id, ehash }) { + return responseHandler(await api.put('/subscriber', { id, ehash })) +} + +/* + * Confirm newsletter unsubscribe + */ +Backend.prototype.confirmNewsletterUnsubscribe = async function ({ id, ehash }) { + return responseHandler(await api.delete('/subscriber', { id, ehash })) } export function useBackend(token = false) {