small a11y fixes
This commit is contained in:
parent
9078c0315d
commit
a8874c82ba
|
@ -24,6 +24,8 @@ There are several environment variables you can set to configure how the crawler
|
||||||
- `FRONTEND_DOMAIN` (required). Used to generate login links for instance admins.
|
- `FRONTEND_DOMAIN` (required). Used to generate login links for instance admins.
|
||||||
- Don't enter `https://`, this is added automatically.
|
- Don't enter `https://`, this is added automatically.
|
||||||
- `SENDGRID_API_KEY`. Needed to send emails to the admin, or to instance admins who want to opt in/out.
|
- `SENDGRID_API_KEY`. Needed to send emails to the admin, or to instance admins who want to opt in/out.
|
||||||
|
- `MASTODON_DOMAIN`. The domain (e.g. `mastodon.social`) that your bot login account is hosted on.
|
||||||
|
- `MASTODON_TOKEN`. The access token for the bot login account.
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,12 @@ defmodule BackendWeb.RateLimiter do
|
||||||
end
|
end
|
||||||
|
|
||||||
def rate_limit_authentication(conn, options \\ []) do
|
def rate_limit_authentication(conn, options \\ []) do
|
||||||
%{"id" => domain} = conn.params
|
domain =
|
||||||
|
if Map.has_key?(conn.params, "id") do
|
||||||
|
Map.get(conn.params, "id")
|
||||||
|
else
|
||||||
|
Map.get(conn.params, "domain")
|
||||||
|
end
|
||||||
options = Keyword.put(options, :bucket_name, "authorization: #{domain}")
|
options = Keyword.put(options, :bucket_name, "authorization: #{domain}")
|
||||||
rate_limit(conn, options)
|
rate_limit(conn, options)
|
||||||
end
|
end
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
"@types/node": "^14.0.1",
|
"@types/node": "^14.0.1",
|
||||||
"@types/numeral": "^0.0.28",
|
"@types/numeral": "^0.0.28",
|
||||||
"@types/react": "^16.9.35",
|
"@types/react": "^16.9.35",
|
||||||
|
"@types/react-axe": "^3.1.0",
|
||||||
"@types/react-dom": "^16.9.8",
|
"@types/react-dom": "^16.9.8",
|
||||||
"@types/react-redux": "^7.1.8",
|
"@types/react-redux": "^7.1.8",
|
||||||
"@types/react-router-dom": "^5.1.5",
|
"@types/react-router-dom": "^5.1.5",
|
||||||
|
@ -79,7 +80,7 @@
|
||||||
"husky": "^4.2.5",
|
"husky": "^4.2.5",
|
||||||
"lint-staged": "^10.2.4",
|
"lint-staged": "^10.2.4",
|
||||||
"prettier": "^2.0.5",
|
"prettier": "^2.0.5",
|
||||||
"react-axe": "^3.3.0",
|
"react-axe": "3.3.0",
|
||||||
"typescript": "^3.9.2"
|
"typescript": "^3.9.2"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|
|
@ -19,6 +19,7 @@ const AppRouter: React.FC = () => (
|
||||||
<ConnectedRouter history={history}>
|
<ConnectedRouter history={history}>
|
||||||
<div className={`${Classes.DARK} App`}>
|
<div className={`${Classes.DARK} App`}>
|
||||||
<Nav />
|
<Nav />
|
||||||
|
<main role="main">
|
||||||
<Route path="/instances" exact component={TableScreen} />
|
<Route path="/instances" exact component={TableScreen} />
|
||||||
<Route path="/about" exact component={AboutScreen} />
|
<Route path="/about" exact component={AboutScreen} />
|
||||||
<Route path="/admin/login" exact component={LoginScreen} />
|
<Route path="/admin/login" exact component={LoginScreen} />
|
||||||
|
@ -26,6 +27,7 @@ const AppRouter: React.FC = () => (
|
||||||
<Route path="/admin" exact component={AdminScreen} />
|
<Route path="/admin" exact component={AdminScreen} />
|
||||||
{/* We always want the GraphScreen to be rendered (since un- and re-mounting it is expensive */}
|
{/* We always want the GraphScreen to be rendered (since un- and re-mounting it is expensive */}
|
||||||
<GraphScreen />
|
<GraphScreen />
|
||||||
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</ConnectedRouter>
|
</ConnectedRouter>
|
||||||
);
|
);
|
||||||
|
|
|
@ -143,7 +143,7 @@ class InstanceTable extends React.PureComponent<InstanceTableProps> {
|
||||||
const isEndOfSection = nextPage !== undefined && page + 1 !== nextPage && page !== totalPages;
|
const isEndOfSection = nextPage !== undefined && page + 1 !== nextPage && page !== totalPages;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<React.Fragment key={page}>
|
||||||
<Button
|
<Button
|
||||||
key={page}
|
key={page}
|
||||||
onClick={this.loadPageFactory(page)}
|
onClick={this.loadPageFactory(page)}
|
||||||
|
@ -157,7 +157,7 @@ class InstanceTable extends React.PureComponent<InstanceTableProps> {
|
||||||
...
|
...
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
|
@ -21,30 +21,31 @@ class Nav extends React.Component<{}, NavState> {
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<Navbar fixedToTop>
|
<nav role="navigation">
|
||||||
|
<Navbar fixedToTop={true}>
|
||||||
<Navbar.Group align={Alignment.LEFT}>
|
<Navbar.Group align={Alignment.LEFT}>
|
||||||
<Navbar.Heading>fediverse.space</Navbar.Heading>
|
<Navbar.Heading>fediverse.space</Navbar.Heading>
|
||||||
<Navbar.Divider />
|
<Navbar.Divider />
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/"
|
to="/"
|
||||||
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.GLOBE_NETWORK}`}
|
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.GLOBE_NETWORK}`}
|
||||||
activeClassName={Classes.INTENT_PRIMARY}
|
|
||||||
isActive={graphIsActive as any}
|
isActive={graphIsActive as any}
|
||||||
|
activeClassName="current-navbar-item"
|
||||||
>
|
>
|
||||||
Home
|
Home
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/instances"
|
to="/instances"
|
||||||
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.TH}`}
|
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.TH}`}
|
||||||
activeClassName={Classes.INTENT_PRIMARY}
|
activeClassName="current-navbar-item"
|
||||||
>
|
>
|
||||||
Instances
|
Instances
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/about"
|
to="/about"
|
||||||
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.INFO_SIGN}`}
|
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.INFO_SIGN}`}
|
||||||
activeClassName={Classes.INTENT_PRIMARY}
|
activeClassName="current-navbar-item"
|
||||||
exact
|
exact={true}
|
||||||
>
|
>
|
||||||
About
|
About
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
@ -53,12 +54,13 @@ class Nav extends React.Component<{}, NavState> {
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/admin"
|
to="/admin"
|
||||||
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.COG}`}
|
className={`${Classes.BUTTON} ${Classes.MINIMAL} bp3-icon-${IconNames.COG}`}
|
||||||
activeClassName={Classes.INTENT_PRIMARY}
|
activeClassName="current-navbar-item"
|
||||||
>
|
>
|
||||||
Administration
|
Administration
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</Navbar.Group>
|
</Navbar.Group>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Classes, Code, H1, H2, H4 } from "@blueprintjs/core";
|
import { Classes, Code, H1, H2, H3 } from "@blueprintjs/core";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
// import appsignalLogo from "../../assets/appsignal.svg";
|
// import appsignalLogo from "../../assets/appsignal.svg";
|
||||||
|
@ -36,16 +36,16 @@ const AboutScreen: React.FC = () => (
|
||||||
<br />
|
<br />
|
||||||
<H2>FAQ</H2>
|
<H2>FAQ</H2>
|
||||||
|
|
||||||
<H4>Why can't I see details about my instance?</H4>
|
<H3>Why can't I see details about my instance?</H3>
|
||||||
<p className={Classes.RUNNING_TEXT}>
|
<p className={Classes.RUNNING_TEXT}>
|
||||||
fediverse.space only supports servers using the Mastodon API, the Misskey API, the GNU Social API, or Nodeinfo.
|
fediverse.space only supports servers using the Mastodon API, the Misskey API, the GNU Social API, or Nodeinfo.
|
||||||
Instances with 10 or fewer users won't be crawled -- it's a tool for understanding communities, not
|
Instances with 10 or fewer users won't be crawled -- it's a tool for understanding communities, not
|
||||||
individuals.
|
individuals.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<H4>
|
<H3>
|
||||||
When is <Code>$OTHER_FEDIVERSE_SERVER</Code> going to be added?
|
When is <Code>$OTHER_FEDIVERSE_SERVER</Code> going to be added?
|
||||||
</H4>
|
</H3>
|
||||||
<p className={Classes.RUNNING_TEXT}>
|
<p className={Classes.RUNNING_TEXT}>
|
||||||
Check out{" "}
|
Check out{" "}
|
||||||
<a href="https://gitlab.com/taobojlen/fediverse.space/issues/24" target="_blank" rel="noopener noreferrer">
|
<a href="https://gitlab.com/taobojlen/fediverse.space/issues/24" target="_blank" rel="noopener noreferrer">
|
||||||
|
@ -54,10 +54,10 @@ const AboutScreen: React.FC = () => (
|
||||||
.
|
.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<H4>How do I add my personal instance?</H4>
|
<H3>How do I add my personal instance?</H3>
|
||||||
<p className={Classes.RUNNING_TEXT}>Click on the Administration link in the top right to opt-in.</p>
|
<p className={Classes.RUNNING_TEXT}>Click on the Administration link in the top right to opt-in.</p>
|
||||||
|
|
||||||
<H4>How do you calculate the strength of relationships between instances?</H4>
|
<H3>How do you calculate the strength of relationships between instances?</H3>
|
||||||
<p className={Classes.RUNNING_TEXT}>
|
<p className={Classes.RUNNING_TEXT}>
|
||||||
fediverse.space looks at public statuses from within the last month on the public timeline of each instance. It
|
fediverse.space looks at public statuses from within the last month on the public timeline of each instance. It
|
||||||
calculates at the ratio of
|
calculates at the ratio of
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Button, Classes, FormGroup, H1, H4, Icon, InputGroup, Intent } from "@blueprintjs/core";
|
import { Button, Classes, FormGroup, H1, H2, Icon, InputGroup, Intent } from "@blueprintjs/core";
|
||||||
import { IconNames } from "@blueprintjs/icons";
|
import { IconNames } from "@blueprintjs/icons";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Redirect } from "react-router";
|
import { Redirect } from "react-router";
|
||||||
|
@ -132,7 +132,7 @@ class LoginScreen extends React.PureComponent<{}, LoginScreenState> {
|
||||||
const loginWithDm = () => this.login("fediverseAccount");
|
const loginWithDm = () => this.login("fediverseAccount");
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<H4>Choose an authentication method</H4>
|
<H2>Choose an authentication method</H2>
|
||||||
<LoginTypeContainer>
|
<LoginTypeContainer>
|
||||||
{loginTypes.email && (
|
{loginTypes.email && (
|
||||||
<LoginTypeButton large icon={IconNames.ENVELOPE} onClick={loginWithEmail} loading={!!isSendingLoginRequest}>
|
<LoginTypeButton large icon={IconNames.ENVELOPE} onClick={loginWithEmail} loading={!!isSendingLoginRequest}>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Button, Callout, H2, InputGroup, Intent, NonIdealState, Spinner } from "@blueprintjs/core";
|
import { Button, Callout, H1, InputGroup, Intent, NonIdealState, Spinner } from "@blueprintjs/core";
|
||||||
import { IconNames } from "@blueprintjs/icons";
|
import { IconNames } from "@blueprintjs/icons";
|
||||||
import { push } from "connected-react-router";
|
import { push } from "connected-react-router";
|
||||||
import { get, isEqual } from "lodash";
|
import { get, isEqual } from "lodash";
|
||||||
|
@ -121,7 +121,7 @@ class SearchScreen extends React.PureComponent<SearchScreenProps, SearchScreenSt
|
||||||
<>
|
<>
|
||||||
{isSmallScreen && results.length === 0 && this.renderMobileWarning()}
|
{isSmallScreen && results.length === 0 && this.renderMobileWarning()}
|
||||||
<SearchBarContainer hasSearchResults={!!query && !!results} hasError={!!error}>
|
<SearchBarContainer hasSearchResults={!!query && !!results} hasError={!!error}>
|
||||||
<H2>Find an instance</H2>
|
<H1>Find an instance</H1>
|
||||||
<InputGroup
|
<InputGroup
|
||||||
leftIcon={IconNames.SEARCH}
|
leftIcon={IconNames.SEARCH}
|
||||||
rightElement={rightSearchBarElement}
|
rightElement={rightSearchBarElement}
|
||||||
|
|
|
@ -12,3 +12,7 @@ body {
|
||||||
.app-toaster {
|
.app-toaster {
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.current-navbar-item {
|
||||||
|
background-color: #293742 !important;
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,11 @@ import { createBrowserHistory } from "history";
|
||||||
import AppRouter from "./AppRouter";
|
import AppRouter from "./AppRouter";
|
||||||
import createRootReducer from "./redux/reducers";
|
import createRootReducer from "./redux/reducers";
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === "development") {
|
||||||
|
const axe = require("react-axe"); // eslint-disable-line @typescript-eslint/no-var-requires
|
||||||
|
axe(React, ReactDOM, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
// https://blueprintjs.com/docs/#core/accessibility.focus-management
|
// https://blueprintjs.com/docs/#core/accessibility.focus-management
|
||||||
FocusStyleManager.onlyShowFocusOnTabs();
|
FocusStyleManager.onlyShowFocusOnTabs();
|
||||||
|
|
||||||
|
|
|
@ -1573,7 +1573,16 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
|
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
|
||||||
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
|
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
|
||||||
|
|
||||||
"@types/react-dom@^16.9.8":
|
"@types/react-axe@^3.1.0":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-axe/-/react-axe-3.1.0.tgz#d8bd3f3f1077e7e2790c2a500f3ccefde8f5567b"
|
||||||
|
integrity sha512-zBQGSlWVwiMiKmDsFS5+2uO5tt1M2fdD3mTkOAA4EwV2uWrzi02d5NMhLZtxpyaCWtwz5xNLO4INotoWZUAg0A==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
"@types/react-dom" "*"
|
||||||
|
axe-core "3.2.2"
|
||||||
|
|
||||||
|
"@types/react-dom@*", "@types/react-dom@^16.9.8":
|
||||||
version "16.9.8"
|
version "16.9.8"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
|
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
|
||||||
integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==
|
integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==
|
||||||
|
@ -2245,7 +2254,12 @@ aws4@^1.8.0:
|
||||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
|
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
|
||||||
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
|
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
|
||||||
|
|
||||||
axe-core@^3.5.0:
|
axe-core@3.2.2:
|
||||||
|
version "3.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.2.2.tgz#b06d6e9ae4636d706068843272bfaeed3fe97362"
|
||||||
|
integrity sha512-gAy4kMSPpuRJV3mwictJqlg5LhE84Vw2CydKdC4tvrLhR6+G3KW51zbL/vYujcLA2jvWOq3HMHrVeNuw+mrLVA==
|
||||||
|
|
||||||
|
axe-core@^3.3.2:
|
||||||
version "3.5.3"
|
version "3.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.3.tgz#5b7c0ee7c5197d546bd3a07c3ef701896f5773e9"
|
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.3.tgz#5b7c0ee7c5197d546bd3a07c3ef701896f5773e9"
|
||||||
integrity sha512-HZpLE7xu05+8AbpqXITGdxp1Xwk8ysAXrg7MiKRY27py3DAyEJpoJQo1727pWF3F+O79V3r+cTWhOzfB49P89w==
|
integrity sha512-HZpLE7xu05+8AbpqXITGdxp1Xwk8ysAXrg7MiKRY27py3DAyEJpoJQo1727pWF3F+O79V3r+cTWhOzfB49P89w==
|
||||||
|
@ -9198,12 +9212,12 @@ react-app-polyfill@^1.0.6:
|
||||||
regenerator-runtime "^0.13.3"
|
regenerator-runtime "^0.13.3"
|
||||||
whatwg-fetch "^3.0.0"
|
whatwg-fetch "^3.0.0"
|
||||||
|
|
||||||
react-axe@^3.3.0:
|
react-axe@3.3.0:
|
||||||
version "3.4.1"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-axe/-/react-axe-3.4.1.tgz#8874ca48b5af71452d97c2991d37cdcbba6c3a48"
|
resolved "https://registry.yarnpkg.com/react-axe/-/react-axe-3.3.0.tgz#b87bff644ed3ed6f1ca12bcc64c00000e359c25b"
|
||||||
integrity sha512-1UDeqesgb5gCj2XPE5WXqKv2xcwGGeWIock3uBVtZSVGbZGVzjmgYf4eRyNJ8BNnHpPQKUs4Ro5jW2+V037deg==
|
integrity sha512-JoxU2jcTla37U6MtqIoYnGaRQcAHkNm9JxTjx2wcEgFm8Zd2A2vo9eboxcmpLjklXDKJwJNbyDo2Jcbbme6xwA==
|
||||||
dependencies:
|
dependencies:
|
||||||
axe-core "^3.5.0"
|
axe-core "^3.3.2"
|
||||||
requestidlecallback "^0.3.0"
|
requestidlecallback "^0.3.0"
|
||||||
|
|
||||||
react-dev-utils@^10.2.1:
|
react-dev-utils@^10.2.1:
|
||||||
|
|
Loading…
Reference in a new issue