From da465d2266f1d559f2c6e18306eddd77dd54e12e Mon Sep 17 00:00:00 2001 From: Adam Siekierski Date: Thu, 31 Dec 2020 20:47:33 +0100 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20Na=20podstawie=20linka=20do=20artyk?= =?UTF-8?q?u=C5=82u=20lub/i=20tytu=C5=82u=20bloga,=20okre=C5=9Bla=20czy=20?= =?UTF-8?q?jest=20podcastem,=20kana=C5=82em=20na=20YT=20czy=20zwyk=C5=82ym?= =?UTF-8?q?=20blogiem=20(#89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Detect creator type for redirect in article page * Remove redundant import * YT fix * CR --- components/ArticleSection/ArticleSection.tsx | 13 +++++++++++-- utils/creator-utils.ts | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 utils/creator-utils.ts diff --git a/components/ArticleSection/ArticleSection.tsx b/components/ArticleSection/ArticleSection.tsx index def2c0cf..8fa308ef 100644 --- a/components/ArticleSection/ArticleSection.tsx +++ b/components/ArticleSection/ArticleSection.tsx @@ -2,17 +2,26 @@ import Link from 'next/link'; import { memo } from 'react'; import type { ArticlePageProps } from '../../pages/artykuly/[slug]'; +import { detectContentGenre } from '../../utils/creator-utils'; import { formatDate } from '../../utils/date-utils'; import { addTrackingToLink } from '../../utils/link-utils'; import { Button } from '../Button/Button'; import styles from './articleSection.module.scss'; +const linkLabels: Record, string> = { + blog: 'Przejdź do artykułu', + podcast: 'Przejdź do podcastu', + youtube: 'Przejdź do filmu', +}; + type ArticleSectionProps = Pick; export const ArticleSection = memo(({ article }) => { const readableDate = formatDate(article.publishedAt); + const articleLinkLabel = linkLabels[detectContentGenre(article)]; + return (

@@ -42,10 +51,10 @@ export const ArticleSection = memo(({ article }) => {
-

Chcesz więcej? Przeczytaj w oryginale!

+

Chcesz więcej? Sprawdź w oryginale!

diff --git a/utils/creator-utils.ts b/utils/creator-utils.ts new file mode 100644 index 00000000..516a38ce --- /dev/null +++ b/utils/creator-utils.ts @@ -0,0 +1,17 @@ +import type { ArticlePageProps } from '../pages/artykuly/[slug]'; + +// Detect YouTube videos by the article URL +const ytRegex = /youtu(\.be|be\.com)\//; + +// Detect podcasts by the anchor.fm in article URL (most popular hosting) or podcast name (common words like talk or podcast) +const podcastRegex = /(anchor\.fm\/|talk|podcast)/i; + +export const detectContentGenre = (article: ArticlePageProps['article']) => { + if (ytRegex.test(article.href)) { + return 'youtube' as const; + } else if (podcastRegex.test(article.href) || podcastRegex.test(article.blog.name)) { + return 'podcast' as const; + } else { + return 'blog' as const; + } +}; From f432fcc165c416ba4f70a8642c7ed408018bd295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miszczyszyn?= Date: Thu, 31 Dec 2020 20:58:35 +0100 Subject: [PATCH 2/7] Sentry (#91) Co-authored-by: Adam Siekierski --- package.json | 2 ++ utils/sentry.ts | 6 ++++++ yarn.lock | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/package.json b/package.json index dbca4ca5..8e7f956c 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,8 @@ "@sentry/browser": "5.29.2", "@sentry/integrations": "5.29.2", "@sentry/node": "5.29.2", + "@sentry/react": "5.29.2", + "@sentry/tracing": "5.29.2", "@sentry/webpack-plugin": "1.14.0", "@zeit/next-source-maps": "0.0.4-canary.1", "cheerio": "1.0.0-rc.5", diff --git a/utils/sentry.ts b/utils/sentry.ts index 09e1eaaf..00fb5393 100644 --- a/utils/sentry.ts +++ b/utils/sentry.ts @@ -1,6 +1,7 @@ // https://github.com/vercel/next.js/blob/db329fe9b0e13a389a84cb98fd936e8a671ba8ec/examples/with-sentry/utils/sentry.js import { RewriteFrames } from '@sentry/integrations'; import * as Sentry from '@sentry/node'; +import { Integrations } from '@sentry/tracing'; export const initSentry = () => { if (process.env.NEXT_PUBLIC_SENTRY_DSN) { @@ -21,6 +22,10 @@ export const initSentry = () => { }, }), ); + integrations.push(new Sentry.Integrations.Http({ tracing: true })); + } + if (process.env.NEXT_IS_SERVER !== 'true') { + integrations.push(new Integrations.BrowserTracing()); } Sentry.init({ @@ -28,6 +33,7 @@ export const initSentry = () => { integrations, dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, release: process.env.NEXT_PUBLIC_COMMIT_SHA, + tracesSampleRate: 1.0, }); } }; diff --git a/yarn.lock b/yarn.lock index f4cb4894..9746a130 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1505,6 +1505,18 @@ lru_map "^0.3.3" tslib "^1.9.3" +"@sentry/react@5.29.2": + version "5.29.2" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-5.29.2.tgz#e0e2055db6f9c7a3957630e726b23d6a0f2d12f2" + integrity sha512-Fvh4l6/wrnO3FWqte7lPUsuWE5o6t3FHwZqVINgCIabpwPMorvOVzm/gwG7uzhuCoyNTP28svR670sl4BnRuTg== + dependencies: + "@sentry/browser" "5.29.2" + "@sentry/minimal" "5.29.2" + "@sentry/types" "5.29.2" + "@sentry/utils" "5.29.2" + hoist-non-react-statics "^3.3.2" + tslib "^1.9.3" + "@sentry/tracing@5.29.2": version "5.29.2" resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.29.2.tgz#6012788547d2ab7893799d82c4941bda145dcd47" From 2fa27f41c26747e1c292511be39d0c69c1c2c138 Mon Sep 17 00:00:00 2001 From: Michal Miszczyszyn Date: Thu, 31 Dec 2020 20:59:56 +0100 Subject: [PATCH 3/7] v3.6.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8e7f956c..4decb0c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "polskifrontend", - "version": "3.5.0", + "version": "3.6.0", "np": { "branch": "main", "releaseDraft": true From edf732c2034e81a390d4d15f1adfc16aa0347640 Mon Sep 17 00:00:00 2001 From: Michal Miszczyszyn Date: Fri, 1 Jan 2021 02:42:30 +0100 Subject: [PATCH 4/7] Move to Europe --- vercel.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 vercel.json diff --git a/vercel.json b/vercel.json new file mode 100644 index 00000000..ec571df7 --- /dev/null +++ b/vercel.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/ph1p/zeit-co-vscode-schemas/master/schemas/vercel.json", + "regions": ["dub1"] +} From 11e5099ea32c88da32d91d6046df588cd3b5a33c Mon Sep 17 00:00:00 2001 From: Michal Miszczyszyn Date: Fri, 1 Jan 2021 02:44:20 +0100 Subject: [PATCH 5/7] Revert "Move to Europe" This reverts commit edf732c2034e81a390d4d15f1adfc16aa0347640. --- vercel.json | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 vercel.json diff --git a/vercel.json b/vercel.json deleted file mode 100644 index ec571df7..00000000 --- a/vercel.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/ph1p/zeit-co-vscode-schemas/master/schemas/vercel.json", - "regions": ["dub1"] -} From efb36cd9d01ee67321f3da8309996ef1a5cac863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miszczyszyn?= Date: Fri, 1 Jan 2021 02:53:34 +0100 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20Przeniesiono=20instancj=C4=99=20Verc?= =?UTF-8?q?ela=20do=20Europy=20zamiast=20USA=20w=20celu=20znacznego=20przy?= =?UTF-8?q?=C5=9Bpieszenia=20dzia=C5=82ania=20API=20routes=20(#92)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Revert "Revert "Move to Europe"" This reverts commit 11e5099ea32c88da32d91d6046df588cd3b5a33c. * Move to Europe --- vercel.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 vercel.json diff --git a/vercel.json b/vercel.json new file mode 100644 index 00000000..4fb7bbca --- /dev/null +++ b/vercel.json @@ -0,0 +1,3 @@ +{ + "regions": ["dub1"] +} From abb7b53757d0768ad6e8d7be5fa9171da5efa0a0 Mon Sep 17 00:00:00 2001 From: Adam Siekierski Date: Fri, 1 Jan 2021 18:09:31 +0100 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20Dodano=20wyj=C4=85tek=20dla=20ju?= =?UTF-8?q?=C5=BC=20dodanego=20bloga=20w=20formularzu=20(#94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add message for already added blog * CR * CR * fix * cr --- .../AddContentCreatorForm.tsx | 7 +- .../AddContentCreatorForm/FormStatus.tsx | 71 +++++++++---------- hooks/useAddContentCreatorMutation.tsx | 28 -------- hooks/useMutation.tsx | 28 ++++++++ pages/api/content-creator.ts | 2 +- utils/api/addContentCreator.ts | 2 +- 6 files changed, 68 insertions(+), 70 deletions(-) delete mode 100644 hooks/useAddContentCreatorMutation.tsx create mode 100644 hooks/useMutation.tsx diff --git a/components/AddContentCreatorForm/AddContentCreatorForm.tsx b/components/AddContentCreatorForm/AddContentCreatorForm.tsx index e189740d..1b437e04 100644 --- a/components/AddContentCreatorForm/AddContentCreatorForm.tsx +++ b/components/AddContentCreatorForm/AddContentCreatorForm.tsx @@ -3,7 +3,8 @@ import clsx from 'clsx'; import type { ChangeEventHandler, FormEventHandler } from 'react'; import { useEffect, useRef, useCallback, useState } from 'react'; -import { useAddContentCreatorMutation } from '../../hooks/useAddContentCreatorMutation'; +import { useMutation } from '../../hooks/useMutation'; +import { addContentCreator } from '../../utils/api/addContentCreator'; import { Button } from '../Button/Button'; import { FormStatus } from './FormStatus'; @@ -12,11 +13,11 @@ import styles from './addContentCreatorForm.module.scss'; export const AddContentCreatorForm = () => { const [fields, setFields] = useState({ contentURL: '', email: '' }); const [token, setToken] = useState(null); - const [mutate, status] = useAddContentCreatorMutation(); const [touched, setTouched] = useState>({}); const captchaRef = useRef(null); const formRef = useRef(null); const [isFormValid, setIsFormValid] = useState(false); + const { mutate, status, errorCode } = useMutation(addContentCreator); useEffect(() => { if (status === 'success') { @@ -110,7 +111,7 @@ export const AddContentCreatorForm = () => { Zgłoś
- + ); }; diff --git a/components/AddContentCreatorForm/FormStatus.tsx b/components/AddContentCreatorForm/FormStatus.tsx index 5807082d..80f5599b 100644 --- a/components/AddContentCreatorForm/FormStatus.tsx +++ b/components/AddContentCreatorForm/FormStatus.tsx @@ -1,55 +1,52 @@ import clsx from 'clsx'; import { memo } from 'react'; -import type { Status } from '../../hooks/useAddContentCreatorMutation'; +import type { Status } from '../../hooks/useMutation'; import styles from './FormStatus.module.css'; type Props = { readonly status: Status; + readonly errorCode?: number; }; -export const FormStatus = memo(({ status }) => { +const errorToMessage: Record = { + 409: 'Blog o podanym adresie został już dodany do naszej bazy danych. Jeżeli nie pojawiają się najnowsze wpisy, lub masz inne zastrzeżenia - proszę skontaktuj się z administratorem.', + 422: 'Nie udało się odnaleźć pliku RSS na twojej stronie, jeśli ten błąd się powtarza, proszę skontaktuj się z administratorem.', +}; + +const defaultErrorMessage = + 'Wystąpił błąd podczas dodawania nowego serwisu, sprawdź poprawność danych i spróbuj ponownie'; + +function getStatusMessage({ status, errorCode }: Props) { switch (status) { case 'loading': - return ( -
- - Oczekiwanie... -
- ); - case 'error': - return ( -
- - - Wystąpił błąd podczas dodawania nowego serwisu, sprawdź poprawność danych i spróbuj - ponownie - -
- ); - case 'notRssFound': - return ( -
- - - Nie udało się odnaleźć pliku rss na twojej stronie, jeśli ten błąd się powtarza, proszę - skontaktuj się z administratorem. - -
- ); + return 'Oczekiwanie...'; case 'success': - return ( -
- - - Dziękujemy za zgłoszenie, dodany serwis pojawi się na stronie po zaakceptowaniu przez - administrację - -
- ); + return 'Dziękujemy za zgłoszenie, dodany serwis pojawi się na stronie po zaakceptowaniu przez administrację'; + case 'error': + return errorCode ? errorToMessage[errorCode] ?? defaultErrorMessage : defaultErrorMessage; default: return null; } +} + +export const FormStatus = memo(({ status, errorCode }) => { + if (status === 'idle') { + return null; + } + + return ( +
+ + {getStatusMessage({ status, errorCode })} +
+ ); }); FormStatus.displayName = 'FormStatus'; diff --git a/hooks/useAddContentCreatorMutation.tsx b/hooks/useAddContentCreatorMutation.tsx deleted file mode 100644 index 7987a798..00000000 --- a/hooks/useAddContentCreatorMutation.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { useCallback, useState } from 'react'; - -import type { ContentCreatorReqBody } from '../utils/api/addContentCreator'; -import { addContentCreator } from '../utils/api/addContentCreator'; - -export type Status = 'idle' | 'loading' | 'error' | 'success' | 'notRssFound'; - -export const useAddContentCreatorMutation = () => { - const [status, setStatus] = useState('idle'); - - const mutate = useCallback(async (body: ContentCreatorReqBody) => { - setStatus('loading'); - try { - const response = await addContentCreator(body); - if (response.ok) { - setStatus('success'); - } else if (response.status === 422) { - setStatus('notRssFound'); - } else { - setStatus('error'); - } - } catch (err) { - setStatus('error'); - } - }, []); - - return [mutate, status] as const; -}; diff --git a/hooks/useMutation.tsx b/hooks/useMutation.tsx new file mode 100644 index 00000000..1d1d7e77 --- /dev/null +++ b/hooks/useMutation.tsx @@ -0,0 +1,28 @@ +import { useCallback, useState } from 'react'; + +export type Status = 'idle' | 'loading' | 'error' | 'success'; + +export function useMutation(mutation: (body: Body) => Promise) { + const [status, setStatus] = useState<{ readonly status: Status; readonly errorCode?: number }>({ + status: 'idle', + }); + + const mutate = useCallback( + async (body: Body) => { + setStatus({ status: 'loading' }); + try { + const response = await mutation(body); + if (response.ok) { + setStatus({ status: 'success' }); + } else { + setStatus({ status: 'error', errorCode: response.status }); + } + } catch (err) { + setStatus({ status: 'error' }); + } + }, + [mutation], + ); + + return { mutate, ...status } as const; +} diff --git a/pages/api/content-creator.ts b/pages/api/content-creator.ts index 6ac13d1d..7e51c983 100644 --- a/pages/api/content-creator.ts +++ b/pages/api/content-creator.ts @@ -30,7 +30,7 @@ export default withAsync( const url = new URL(req.body.contentURL).toString(); const contentCreator = await addContentCreator(url, req.body.email); - await sendNewCreatorNotification(contentCreator); + await sendNewCreatorNotification(contentCreator).catch(() => {}); return null; }), diff --git a/utils/api/addContentCreator.ts b/utils/api/addContentCreator.ts index f79d81ff..a09a65d6 100644 --- a/utils/api/addContentCreator.ts +++ b/utils/api/addContentCreator.ts @@ -5,7 +5,7 @@ export type ContentCreatorReqBody = { }; export const addContentCreator = (requestBody: ContentCreatorReqBody) => { - return fetch(`https://${process.env.NEXT_PUBLIC_URL as string}/api/content-creator`, { + return fetch(`/api/content-creator`, { method: 'POST', body: JSON.stringify(requestBody), });