Skip to content
Snippets Groups Projects
Commit f8020a16 authored by xaralis's avatar xaralis
Browse files

feat: add og meta tags for better sharing experience

parent 2dd3c52f
No related branches found
No related tags found
No related merge requests found
......@@ -14556,6 +14556,17 @@
}
}
},
"react-helmet": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
"integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
"requires": {
"object-assign": "^4.1.1",
"prop-types": "^15.7.2",
"react-fast-compare": "^3.1.1",
"react-side-effect": "^2.1.0"
}
},
"react-intersection-observer": {
"version": "8.31.0",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.31.0.tgz",
......@@ -15017,6 +15028,11 @@
}
}
},
"react-side-effect": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz",
"integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ=="
},
"read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
......
public/favicon.ico

3.08 KiB

public/img/og.png

122 KiB

......@@ -17,6 +17,11 @@
<meta property="og:url" content="https://cf2021.pirati.cz/" />
<meta property="og:type" content="website" />
<meta property="og:title" content="CF 2021" />
<meta property="og:image" content="/img/og.png" />
<meta property="og:description" content="Oficiální stránka letošního ročníku Celostátního fóra České pirátské strany." />
<meta name="description" content="Oficiální stránka letošního ročníku Celostátního fóra České pirátské strany." />
<title>CF 2021 | Pirátská strana</title>
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
......@@ -32,7 +37,6 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<link rel="stylesheet" href="%REACT_APP_STYLEGUIDE_URL%/css/styles.css" />
<title>CF 2021 | Pirátská strana</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver"></script>
</head>
<body class="h-screen">
......
public/logo192.png

5.22 KiB

public/logo512.png

9.44 KiB

{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "CF2021",
"name": "Celostátní fórum 2021",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"src": "https://styleguide.pir-test.eu/latest/images/favicons/favicon-32x32.png",
"sizes": "32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
"src": "https://styleguide.pir-test.eu/latest/images/favicons/favicon-96x96.png",
"sizes": "96x96 64x64",
"type": "image/x-icon"
},
{
"src": "logo512.png",
"src": "https://styleguide.pir-test.eu/latest/images/favicons/favicon-196x196.png",
"type": "image/png",
"sizes": "512x512"
"sizes": "192x192 196x196"
}
],
"start_url": ".",
......
import React, { Suspense } from "react";
import { Helmet } from "react-helmet";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { KeycloakProvider } from "@react-keycloak/web";
import * as Sentry from "@sentry/react";
......@@ -6,10 +7,10 @@ import * as Sentry from "@sentry/react";
import { loadConfig } from "actions/global-info";
import { loadMe } from "actions/users";
import { initializeWSChannel } from "actions/ws";
import Button from "components/Button";
import Footer from "components/Footer";
import Navbar from "components/Navbar";
import Home from "pages/Home";
import NotFound from "pages/NotFound";
import Program from "pages/Program";
import Protocol from "pages/Protocol";
import { AuthStore, PostStore } from "stores";
......@@ -80,27 +81,23 @@ const LoadingComponent = (
</div>
);
const NotFound = () => (
<article className="container container--default py-8 lg:py-24">
<h1 className="head-alt-base lg:head-alt-lg mb-8">
404ka: tak tahle stránka tu není
</h1>
<p className="text-base lg:text-xl mb-8">
Dostal/a ses na takzvanou „<strong>čtyřystačtyřku</strong>“, což znamená,
že stránka, kterou jsi se pokusil/a navštívit, na tomhle webu není.
Zkontroluj, zda máš správný odkaz.
</p>
<Button routerTo="/" className="text-base lg:text-xl" hoverActive fullwidth>
Přejít na hlavní stránku
</Button>
</article>
);
const BaseApp = () => {
initializeWSChannel.read();
return (
<Router>
<Helmet>
<title>CF 2021 | Pirátská strana</title>
<meta
name="description"
content="Oficiální stránka letošního ročníku on-line zasedání Celostátního fóra České pirátské strany, 9. 1. 2021."
/>
<meta property="og:title" content="CF 2021" />
<meta
property="og:description"
content="Oficiální stránka letošního ročníku on-line zasedání Celostátního fóra České pirátské strany, 9. 1. 2021."
/>
</Helmet>
<Navbar />
<Switch>
<Route exact path="/" children={<Home />} />
......
......@@ -126,6 +126,7 @@ const Navbar = () => {
<button
onClick={logout}
className="text-grey-200 hover:text-white"
title="Odhlásit se"
>
<i className="ico--log-out"></i>
</button>
......
import React, { useEffect, useState } from "react";
import { Helmet } from "react-helmet";
import Joyride, { EVENTS } from "react-joyride";
import ReactPlayer from "react-player/lazy";
import useWindowSize from "@rooks/use-window-size";
......@@ -109,6 +110,21 @@ const Home = () => {
return (
<>
<Helmet>
<title>Přímý přenos | CF 2021 | Pirátská strana</title>
<meta
name="description"
content="Přímý přenos a diskuse z on-line zasedání Celostátního fóra České pirátské strany, 9. 1. 2021."
/>
<meta
property="og:title"
content="Přímý přenos | CF 2021 | Pirátská strana"
/>
<meta
property="og:description"
content="Přímý přenos a diskuse z on-line zasedání Celostátního fóra České pirátské strany, 9. 1. 2021."
/>
</Helmet>
<Joyride
beaconComponent={Beacon}
continuous={true}
......@@ -259,8 +275,7 @@ const Home = () => {
showAddPostCta={programEntry.discussionOpened}
/>
{!programEntry.discussionOpened &&
isAuthenticated &&
!user.isBanned && (
(!isAuthenticated || (isAuthenticated && !user.isBanned)) && (
<p className="leading-normal">
Rozprava je uzavřena - příspěvky teď nelze přidávat.
</p>
......
import React from "react";
import { Helmet } from "react-helmet";
import Button from "components/Button";
const NotFound = () => (
<>
<Helmet>
<title>404ka | CF 2021 | Pirátská strana</title>
<meta name="description" content="Tahle stránka tu není." />
<meta property="og:title" content="404ka | CF 2021 | Pirátská strana" />
<meta property="og:description" content="Tahle stránka tu není." />
</Helmet>
<article className="container container--default py-8 lg:py-24">
<h1 className="head-alt-base lg:head-alt-lg mb-8">
404ka: tak tahle stránka tu není
</h1>
<p className="text-base lg:text-xl mb-8">
Dostal/a ses na takzvanou „<strong>čtyřystačtyřku</strong>“, což
znamená, že stránka, kterou jsi se pokusil/a navštívit, na tomhle webu
není. Zkontroluj, zda máš správný odkaz.
</p>
<Button
routerTo="/"
className="text-base lg:text-xl"
hoverActive
fullwidth
>
Přejít na hlavní stránku
</Button>
</article>
</>
);
export default NotFound;
import React from "react";
import { Helmet } from "react-helmet";
import { Link } from "react-router-dom";
import { format } from "date-fns";
......@@ -25,79 +26,96 @@ const Schedule = () => {
);
return (
<article className="container container--default py-8 lg:py-24">
<h1 className="head-alt-md lg:head-alt-lg mb-8">Program zasedání</h1>
<div className="flex flex-col">
{scheduleIds.map((id) => {
const isCurrent = id === currentId;
const entry = items[id];
const fullTitle = `${entry.number}. ${entry.title}`;
return (
<div
className="flex flex-col md:flex-row my-4 duration-300 text-black"
key={entry.id}
>
<div className="w-28 md:text-right">
{isCurrent && (
<Chip condensed className="mt-2 mr-2" color="red-600">
Právě probíhá
</Chip>
)}
</div>
<div className="w-full md:w-32 flex flex-row md:flex-col items-center md:items-stretch md:text-right md:pr-8">
<p className="head-heavy-xs md:head-heavy-base">
{format(entry.expectedStartAt, "H:mm")}
</p>
<p className="ml-auto md:ml-0 head-heavy-xs md:head-heavy-xs md:text-grey-200 whitespace-no-wrap">
{format(entry.expectedStartAt, "d. M. Y")}
</p>
</div>
<div className="flex-grow w-full">
<h2 className="head-heavy-xs md:head-heavy-base mb-1">
{isCurrent && <Link to="/">{fullTitle}</Link>}
{!isCurrent && fullTitle}
</h2>
<div className="flex space-x-2">
<strong>Navrhovatel:</strong>
<span>{entry.proposer}</span>
<>
<Helmet>
<title>Program zasedání | CF 2021 | Pirátská strana</title>
<meta
name="description"
content="Přečtěte si program on-line zasedání Celostátního fóra České pirátské strany, 9. 1. 2021."
/>
<meta
property="og:title"
content="Program zasedání | CF 2021 | Pirátská strana"
/>
<meta
property="og:description"
content="Přečtěte si program on-line zasedání Celostátního fóra České pirátské strany, 9. 1. 2021."
/>
</Helmet>
<article className="container container--default py-8 lg:py-24">
<h1 className="head-alt-md lg:head-alt-lg mb-8">Program zasedání</h1>
<div className="flex flex-col">
{scheduleIds.map((id) => {
const isCurrent = id === currentId;
const entry = items[id];
const fullTitle = `${entry.number}. ${entry.title}`;
return (
<div
className="flex flex-col md:flex-row my-4 duration-300 text-black"
key={entry.id}
>
<div className="w-28 md:text-right">
{isCurrent && (
<Chip condensed className="mt-2 mr-2" color="red-600">
Právě probíhá
</Chip>
)}
</div>
{entry.description && (
<p className="mt-2 leading-tight max-w-3xl">
{entry.description}
<div className="w-full md:w-32 flex flex-row md:flex-col items-center md:items-stretch md:text-right md:pr-8">
<p className="head-heavy-xs md:head-heavy-base">
{format(entry.expectedStartAt, "H:mm")}
</p>
)}
{isAuthenticated &&
user.role === "chairman" &&
entry.id !== currentId && (
<div className="mt-4">
<Button
onClick={() => setEntryToActivate(entry)}
color="grey-125"
className="text-xs"
>
Aktivovat tento bod programu
</Button>
</div>
<p className="ml-auto md:ml-0 head-heavy-xs md:head-heavy-xs md:text-grey-200 whitespace-no-wrap">
{format(entry.expectedStartAt, "d. M. Y")}
</p>
</div>
<div className="flex-grow w-full">
<h2 className="head-heavy-xs md:head-heavy-base mb-1">
{isCurrent && <Link to="/">{fullTitle}</Link>}
{!isCurrent && fullTitle}
</h2>
<div className="flex space-x-2">
<strong>Navrhovatel:</strong>
<span>{entry.proposer}</span>
</div>
{entry.description && (
<p className="mt-2 leading-tight max-w-3xl">
{entry.description}
</p>
)}
{isAuthenticated &&
user.role === "chairman" &&
entry.id !== currentId && (
<div className="mt-4">
<Button
onClick={() => setEntryToActivate(entry)}
color="grey-125"
className="text-xs"
>
Aktivovat tento bod programu
</Button>
</div>
)}
</div>
</div>
</div>
);
})}
</div>
<ModalConfirm
isOpen={!!entryToActivate}
onConfirm={onActivateConfirm}
onCancel={onActivateCancel}
confirming={activating}
error={activationError}
title="Aktivovat bod programu?"
yesActionLabel="Aktivovat"
>
Pogramovaný bod{" "}
<strong>{entryToActivate && entryToActivate.title}</strong> bude
aktivován. Chcete pokračovat?
</ModalConfirm>
</article>
);
})}
</div>
<ModalConfirm
isOpen={!!entryToActivate}
onConfirm={onActivateConfirm}
onCancel={onActivateCancel}
confirming={activating}
error={activationError}
title="Aktivovat bod programu?"
yesActionLabel="Aktivovat"
>
Pogramovaný bod{" "}
<strong>{entryToActivate && entryToActivate.title}</strong> bude
aktivován. Chcete pokračovat?
</ModalConfirm>
</article>
</>
);
};
......
import React, { useCallback, useState } from "react";
import { Helmet } from "react-helmet";
import useInterval from "@rooks/use-interval";
import { loadProtocol } from "actions/global-info";
......@@ -54,56 +55,73 @@ const Protocol = () => {
};
return (
<article className="container container--default py-8 lg:py-24">
<h1 className="head-alt-md lg:head-alt-lg mb-8">Zápis z jednání</h1>
<>
<Helmet>
<title>Zápis ze zasedání | CF 2021 | Pirátská strana</title>
<meta
name="description"
content="Interaktivní zápis z on-line zasedání Celostátního fóra České pirátské strany, 9. 1. 2021."
/>
<meta
property="og:title"
content="Zápis ze zasedání | CF 2021 | Pirátská strana"
/>
<meta
property="og:description"
content="Interaktivní zápis z on-line zasedání Celostátního fóra České pirátské strany, 9. 1. 2021."
/>
</Helmet>
<article className="container container--default py-8 lg:py-24">
<h1 className="head-alt-md lg:head-alt-lg mb-8">Zápis z jednání</h1>
<div className="flex items-start">
<div className="lg:w-2/3">
{!protocolUrl && (
<ErrorMessage>Zápis momentálně není k dispozici.</ErrorMessage>
)}
{protocolLoadError && (
<ErrorMessage>
Při stahování záznamu z jednání došlo k problému:{" "}
{protocolLoadError.toString()}
</ErrorMessage>
)}
{protocolUrl && <></>}
{htmlContent && (
<div
className="leading-tight text-sm lg:text-base content-block"
dangerouslySetInnerHTML={htmlContent}
></div>
)}
</div>
<div className="hidden lg:block card elevation-10 w-1/3">
<div className="lg:card__body content-block">
<h2>Jak to funguje?</h2>
<p>
Zápis se aktualizuje automaticky každých 10 sekund. Pokud chceš
aktualizaci vynutit ručně, můžeš využít tlačítko níže.
</p>
<Button
icon="ico--refresh"
loading={protocolLoading}
className="btn--fullwidth"
onClick={forceLoad}
color="black"
bodyProps={{
style: {
position: "relative",
},
}}
>
<span style={progressStyle}></span>
<span style={{ position: "relative" }}>
{protocolLoading ? "Aktualizace..." : "Aktualizovat"}
</span>
</Button>
<div className="flex items-start">
<div className="lg:w-2/3">
{!protocolUrl && (
<ErrorMessage>Zápis momentálně není k dispozici.</ErrorMessage>
)}
{protocolLoadError && (
<ErrorMessage>
Při stahování záznamu z jednání došlo k problému:{" "}
{protocolLoadError.toString()}
</ErrorMessage>
)}
{protocolUrl && <></>}
{htmlContent && (
<div
className="leading-tight text-sm lg:text-base content-block"
dangerouslySetInnerHTML={htmlContent}
></div>
)}
</div>
<div className="hidden lg:block card elevation-10 w-1/3">
<div className="lg:card__body content-block">
<h2>Jak to funguje?</h2>
<p>
Zápis se aktualizuje automaticky každých 10 sekund. Pokud chceš
aktualizaci vynutit ručně, můžeš využít tlačítko níže.
</p>
<Button
icon="ico--refresh"
loading={protocolLoading}
className="btn--fullwidth"
onClick={forceLoad}
color="black"
bodyProps={{
style: {
position: "relative",
},
}}
>
<span style={progressStyle}></span>
<span style={{ position: "relative" }}>
{protocolLoading ? "Aktualizace..." : "Aktualizovat"}
</span>
</Button>
</div>
</div>
</div>
</div>
</article>
</article>
</>
);
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment