feedback-newsletter-bump-wip

This commit is contained in:
tonyrewin 2023-01-30 18:10:27 +03:00
parent 630eba8a94
commit b4ad24e0cf
8 changed files with 60 additions and 57 deletions

View File

@ -9,7 +9,7 @@ const mgOptions = {
const messageData = (subject, text) => { const messageData = (subject, text) => {
return { return {
from: 'Feedback Robot <robot@discours.io>', from: 'Discours Feedback Robot <robot@discours.io>',
to: 'welcome@discours.io', to: 'welcome@discours.io',
subject, subject,
text text
@ -19,12 +19,7 @@ export default async function handler(req, res) {
const { contact, subject, message } = req.query const { contact, subject, message } = req.query
try { try {
const mailgun = new MG(fd) const mailgun = new MG(fd)
const client = mailgun.client({ const client = mailgun.client(mgOptions)
username: mgOptions.username,
key: mgOptions.key
//url?: string;
//public_key?: string;
})
const data = messageData(`${contact}: ${subject}`, message) const data = messageData(`${contact}: ${subject}`, message)
client.messages.create(mgOptions.domain, data).then(console.log).catch(console.error) client.messages.create(mgOptions.domain, data).then(console.log).catch(console.error)
} catch (error) { } catch (error) {

View File

@ -1,27 +1,32 @@
/* eslint-disable unicorn/no-empty-file */
/*
import MG from 'mailgun.js' import MG from 'mailgun.js'
import fd from 'form-data'
const mailgun = new MG({}) const mgOptions = {
const options = { key: process.env.MAILGUN_API_KEY,
apiKey: process.env.MAILGUN_API_KEY, domain: process.env.MAILGUN_DOMAIN,
domain: process.env.MAILGUN_DOMAIN username: 'discoursio' // FIXME
} }
const list = mailgun.lists(process.env.MAILGUN_LIST_ID) // 'services@discours.io'
export default async function handler(req, res) { export default async (req, res) => {
const { email } = req.body.data const { email } = req.query
list.members().create({ subscribed: true, address: email }, (err, data) => { const mailgun = new MG(fd)
if (err) { const client = mailgun.client(mgOptions)
console.error('[newsletter ] error', err)
res.status(500)
} else {
res.status(200).json(data)
}
})
}
*/
export const handler = (req, res) => { try {
return 'WIP' const response = await client.lists.members.createMember(mgOptions.domain, {
address: email,
subscribed: true,
upsert: 'yes'
})
return res.status(200).json({
success: true,
message: 'Email added to newsletter list'
})
} catch (error) {
return res.status(400).json({
success: false,
message: error.message
})
}
} }

View File

@ -25,6 +25,7 @@
"preview": "astro preview", "preview": "astro preview",
"server": "node server/server.mjs", "server": "node server/server.mjs",
"start": "astro dev", "start": "astro dev",
"start:dev": "cross-env PUBLIC_API_URL=http://127.0.0.1:8080 vercel dev",
"start:local": "cross-env PUBLIC_API_URL=http://127.0.0.1:8080 astro dev", "start:local": "cross-env PUBLIC_API_URL=http://127.0.0.1:8080 astro dev",
"start:production": "cross-env PUBLIC_API_URL=https://v2.discours.io astro dev", "start:production": "cross-env PUBLIC_API_URL=https://v2.discours.io astro dev",
"start:staging": "cross-env PUBLIC_API_URL=https://testapi.discours.io astro dev", "start:staging": "cross-env PUBLIC_API_URL=https://testapi.discours.io astro dev",
@ -51,6 +52,7 @@
"@nanostores/solid": "^0.3.2", "@nanostores/solid": "^0.3.2",
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
"@solid-primitives/memo": "^1.1.3", "@solid-primitives/memo": "^1.1.3",
"@solid-primitives/share": "^2.0.1",
"@solid-primitives/storage": "^1.3.4", "@solid-primitives/storage": "^1.3.4",
"@solid-primitives/upload": "^0.0.105", "@solid-primitives/upload": "^0.0.105",
"@types/express": "^4.17.15", "@types/express": "^4.17.15",
@ -63,6 +65,7 @@
"@urql/exchange-graphcache": "^5.0.8", "@urql/exchange-graphcache": "^5.0.8",
"astro": "^2.0.2", "astro": "^2.0.2",
"astro-eslint-parser": "^0.11.0", "astro-eslint-parser": "^0.11.0",
"astro-seo-meta": "^2.0.0",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"bootstrap": "^5.2.3", "bootstrap": "^5.2.3",
"clsx": "^1.2.1", "clsx": "^1.2.1",
@ -120,7 +123,6 @@
"solid-js": "^1.6.9", "solid-js": "^1.6.9",
"solid-js-form": "^0.1.8", "solid-js-form": "^0.1.8",
"solid-jsx": "^0.9.1", "solid-jsx": "^0.9.1",
"solid-social": "^0.9.6",
"solid-utils": "^0.8.1", "solid-utils": "^0.8.1",
"sort-package-json": "^2.3.0", "sort-package-json": "^2.3.0",
"stylelint": "^14.16.1", "stylelint": "^14.16.1",

View File

@ -16,6 +16,7 @@ specifiers:
'@nanostores/solid': ^0.3.2 '@nanostores/solid': ^0.3.2
'@popperjs/core': ^2.11.6 '@popperjs/core': ^2.11.6
'@solid-primitives/memo': ^1.1.3 '@solid-primitives/memo': ^1.1.3
'@solid-primitives/share': ^2.0.1
'@solid-primitives/storage': ^1.3.4 '@solid-primitives/storage': ^1.3.4
'@solid-primitives/upload': ^0.0.105 '@solid-primitives/upload': ^0.0.105
'@types/express': ^4.17.15 '@types/express': ^4.17.15
@ -28,6 +29,7 @@ specifiers:
'@urql/exchange-graphcache': ^5.0.8 '@urql/exchange-graphcache': ^5.0.8
astro: ^2.0.2 astro: ^2.0.2
astro-eslint-parser: ^0.11.0 astro-eslint-parser: ^0.11.0
astro-seo-meta: ^2.0.0
bcryptjs: ^2.4.3 bcryptjs: ^2.4.3
bootstrap: ^5.2.3 bootstrap: ^5.2.3
clsx: ^1.2.1 clsx: ^1.2.1
@ -86,7 +88,6 @@ specifiers:
solid-js: ^1.6.9 solid-js: ^1.6.9
solid-js-form: ^0.1.8 solid-js-form: ^0.1.8
solid-jsx: ^0.9.1 solid-jsx: ^0.9.1
solid-social: ^0.9.6
solid-utils: ^0.8.1 solid-utils: ^0.8.1
sort-package-json: ^2.3.0 sort-package-json: ^2.3.0
stylelint: ^14.16.1 stylelint: ^14.16.1
@ -127,6 +128,7 @@ devDependencies:
'@nanostores/solid': 0.3.2_p2ovwnslwwhnyqciy4vyx3xhn4 '@nanostores/solid': 0.3.2_p2ovwnslwwhnyqciy4vyx3xhn4
'@popperjs/core': 2.11.6 '@popperjs/core': 2.11.6
'@solid-primitives/memo': 1.1.3_solid-js@1.6.9 '@solid-primitives/memo': 1.1.3_solid-js@1.6.9
'@solid-primitives/share': 2.0.1_solid-js@1.6.9
'@solid-primitives/storage': 1.3.4_solid-js@1.6.9 '@solid-primitives/storage': 1.3.4_solid-js@1.6.9
'@solid-primitives/upload': 0.0.105_solid-js@1.6.9 '@solid-primitives/upload': 0.0.105_solid-js@1.6.9
'@types/express': 4.17.15 '@types/express': 4.17.15
@ -139,6 +141,7 @@ devDependencies:
'@urql/exchange-graphcache': 5.0.8_graphql@16.6.0 '@urql/exchange-graphcache': 5.0.8_graphql@16.6.0
astro: 2.0.2_2t5zzertvgx7nxfmkolltgmm7i astro: 2.0.2_2t5zzertvgx7nxfmkolltgmm7i
astro-eslint-parser: 0.11.0 astro-eslint-parser: 0.11.0
astro-seo-meta: 2.0.0_astro@2.0.2
bcryptjs: 2.4.3 bcryptjs: 2.4.3
bootstrap: 5.2.3_@popperjs+core@2.11.6 bootstrap: 5.2.3_@popperjs+core@2.11.6
clsx: 1.2.1 clsx: 1.2.1
@ -196,7 +199,6 @@ devDependencies:
solid-js: 1.6.9 solid-js: 1.6.9
solid-js-form: 0.1.8 solid-js-form: 0.1.8
solid-jsx: 0.9.1_solid-js@1.6.9 solid-jsx: 0.9.1_solid-js@1.6.9
solid-social: 0.9.6_solid-js@1.6.9
solid-utils: 0.8.1_solid-js@1.6.9 solid-utils: 0.8.1_solid-js@1.6.9
sort-package-json: 2.3.0 sort-package-json: 2.3.0
stylelint: 14.16.1 stylelint: 14.16.1
@ -2361,15 +2363,6 @@ packages:
'@sinonjs/commons': 1.8.6 '@sinonjs/commons': 1.8.6
dev: true dev: true
/@solid-primitives/intersection-observer/2.0.4_solid-js@1.6.9:
resolution: {integrity: sha512-QGDgmg2X+buJi4V0h1ajpHnZxTxc+ZUuGTyOLgjHq/EE5HCsPlefXcd5cfk2oiuBca38zQ+NxGZB/5/4fcY6dw==}
peerDependencies:
solid-js: ^1.6.0
dependencies:
'@solid-primitives/utils': 4.0.1_solid-js@1.6.9
solid-js: 1.6.9
dev: true
/@solid-primitives/memo/1.1.3_solid-js@1.6.9: /@solid-primitives/memo/1.1.3_solid-js@1.6.9:
resolution: {integrity: sha512-cVe4kThn/IduZue3C2cbB8TjPbCuhrmpY3DYEqeDktXAhUep4qzqkiAiaJXqTNg1kRV3JNapdr2v8wS3K1PVrw==} resolution: {integrity: sha512-cVe4kThn/IduZue3C2cbB8TjPbCuhrmpY3DYEqeDktXAhUep4qzqkiAiaJXqTNg1kRV3JNapdr2v8wS3K1PVrw==}
peerDependencies: peerDependencies:
@ -2388,8 +2381,8 @@ packages:
solid-js: 1.6.9 solid-js: 1.6.9
dev: true dev: true
/@solid-primitives/script-loader/1.1.3_solid-js@1.6.9: /@solid-primitives/share/2.0.1_solid-js@1.6.9:
resolution: {integrity: sha512-ROr6vjYSGZtJ+qrTRumn+a4GwfWQFEq8S7UphRc3bV3z7JcinEL49mEus7XBuBnswGebx5ofANdp91Iv+GtssA==} resolution: {integrity: sha512-qLiqiVPTVPrhFzCneicDBwlgiuQwqPX2ktfdHjLXjgJsxtyT4nHpTrq6WJV5sBIUt2eb9+dxBKlM6z5Djs1RDw==}
peerDependencies: peerDependencies:
solid-js: ^1.6.0 solid-js: ^1.6.0
dependencies: dependencies:
@ -3138,6 +3131,14 @@ packages:
- supports-color - supports-color
dev: true dev: true
/astro-seo-meta/2.0.0_astro@2.0.2:
resolution: {integrity: sha512-T/c1nQQvmYz0Ub04UooYo6JLZux7OaVwYeolWDf9L7RhpaqyWX80lOczSIt19/9mNKZq1hNYRcJBXWOArI36ug==}
peerDependencies:
astro: ^2.0.0
dependencies:
astro: 2.0.2_2t5zzertvgx7nxfmkolltgmm7i
dev: true
/astro/2.0.2_2t5zzertvgx7nxfmkolltgmm7i: /astro/2.0.2_2t5zzertvgx7nxfmkolltgmm7i:
resolution: {integrity: sha512-47N1jLWNxSri7kWfIfgcEnQJZWTvd0gXhNC3P2ZHiiurl4nOxFC5ULsW5MDDTjTzQ1S7y1RoaL9XxYm+Rury7w==} resolution: {integrity: sha512-47N1jLWNxSri7kWfIfgcEnQJZWTvd0gXhNC3P2ZHiiurl4nOxFC5ULsW5MDDTjTzQ1S7y1RoaL9XxYm+Rury7w==}
engines: {node: '>=16.12.0', npm: '>=6.14.0'} engines: {node: '>=16.12.0', npm: '>=6.14.0'}
@ -9211,16 +9212,6 @@ packages:
solid-js: 1.6.9 solid-js: 1.6.9
dev: true dev: true
/solid-social/0.9.6_solid-js@1.6.9:
resolution: {integrity: sha512-3ZEu5dQR/8kqI7jpCbxErr0SBxTwIWQBbNgab8gNv9mNRWabQ0e2pGT32wpnWUnt50HoSx+hVIRpo/ZY94uxWw==}
peerDependencies:
solid-js: ^1.3.0
dependencies:
'@solid-primitives/intersection-observer': 2.0.4_solid-js@1.6.9
'@solid-primitives/script-loader': 1.1.3_solid-js@1.6.9
solid-js: 1.6.9
dev: true
/solid-utils/0.8.1_solid-js@1.6.9: /solid-utils/0.8.1_solid-js@1.6.9:
resolution: {integrity: sha512-LLeO7Hr99OLFY+Zfx8U7Hw5VZOaFT8qWoLWGfnq3kDmo7KAGdIoq44ijy7mdYj88e+2cWPdkyhItsS3FGjeS6g==} resolution: {integrity: sha512-LLeO7Hr99OLFY+Zfx8U7Hw5VZOaFT8qWoLWGfnq3kDmo7KAGdIoq44ijy7mdYj88e+2cWPdkyhItsS3FGjeS6g==}
peerDependencies: peerDependencies:

View File

@ -8,13 +8,14 @@ export default () => {
const [title, setTitle] = createSignal('') const [title, setTitle] = createSignal('')
const subscribe = async () => { const subscribe = async () => {
setTitle(t('...subscribing')) setTitle(t('...subscribing'))
const r = await fetch(`/maillist?email=${emailElement?.value}`) const r = await fetch(`/api/newsletter?email=${emailElement?.value}`)
setTitle(r.ok ? t('You are subscribed') : '') setTitle(r.ok ? t('You are subscribed') : '')
} }
return ( return (
<div class={styles.subscribeForm}> <div class={styles.subscribeForm}>
<input type="email" name="email" ref={emailElement} placeholder={t('Fill email')} value={title()} /> <label for="email">{title()}</label>
<input type="email" name="email" ref={emailElement} placeholder={t('Fill email')} />
<button <button
class={clsx(styles.button, 'button--light')} class={clsx(styles.button, 'button--light')}
onClick={() => emailElement?.value && subscribe()} onClick={() => emailElement?.value && subscribe()}

View File

@ -1,6 +1,7 @@
import { createSignal, Show } from 'solid-js' import { createSignal, Show } from 'solid-js'
import { PageWrap } from '../../_shared/PageWrap' import { PageWrap } from '../../_shared/PageWrap'
import { Icon } from '../../_shared/Icon' import { Icon } from '../../_shared/Icon'
import { showModal } from '../../../stores/ui'
// const title = t('Terms of use') // const title = t('Terms of use')

View File

@ -6,8 +6,8 @@ import {
subscriptionExchange, subscriptionExchange,
createClient createClient
} from '@urql/core' } from '@urql/core'
import { createClient as createSubClient } from 'graphql-sse' // import { createClient as createSubClient } from 'graphql-sse'
// import { createClient as createSubClient } from 'graphql-ws' import { createClient as createSubClient } from 'graphql-ws'
import { devtoolsExchange } from '@urql/devtools' import { devtoolsExchange } from '@urql/devtools'
import { isDev, apiBaseUrl } from '../utils/config' import { isDev, apiBaseUrl } from '../utils/config'
// import { cache } from './cache' // import { cache } from './cache'
@ -57,7 +57,7 @@ export const privateGraphQLClient = createClient(options)
export const createChatClient = () => { export const createChatClient = () => {
const subClient = createSubClient({ const subClient = createSubClient({
url: apiBaseUrl + '/messages' // .replace('http', 'ws') url: (apiBaseUrl + '/messages').replace('http', 'ws')
}) })
const subExchange = subscriptionExchange({ const subExchange = subscriptionExchange({

View File

@ -4,6 +4,14 @@
"src": "/api/upload", "src": "/api/upload",
"headers": { "Content-Type": "application/json" }, "headers": { "Content-Type": "application/json" },
"dest": "api/upload.py" "dest": "api/upload.py"
},
{
"src": "/api/newsletter",
"dest": "api/newsletter.ts"
},
{
"src": "/api/feedback",
"dest": "api/feedback.ts"
} }
] ]
} }