kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Merge remote-tracking branch 'soapbox/next' into next_
commit
bfd92827d9
|
@ -1,8 +1,8 @@
|
|||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import StickyBox from 'react-sticky-box';
|
||||
|
||||
const Layout = ({ children }) => (
|
||||
const Layout: React.FC = ({ children }) => (
|
||||
<div className='sm:py-4 relative pb-36'>
|
||||
<div className='max-w-3xl mx-auto sm:px-6 md:max-w-7xl md:px-8 md:grid md:grid-cols-12 md:gap-8'>
|
||||
{children}
|
||||
|
@ -11,52 +11,37 @@ const Layout = ({ children }) => (
|
|||
);
|
||||
|
||||
|
||||
const Sidebar = ({ children }) => (
|
||||
const Sidebar: React.FC = ({ children }) => (
|
||||
<div className='hidden lg:block lg:col-span-3'>
|
||||
<div className='sticky top-20'>
|
||||
<StickyBox offsetTop={80} className='pb-4'>
|
||||
{children}
|
||||
</div>
|
||||
</StickyBox>
|
||||
</div>
|
||||
);
|
||||
|
||||
const Main = ({ children, className }) => (
|
||||
const Main: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({ children, className }) => (
|
||||
<main
|
||||
className={classNames({
|
||||
'md:col-span-12 lg:col-span-9 xl:col-span-6 sm:space-y-4': true,
|
||||
[className]: typeof className !== 'undefined',
|
||||
})}
|
||||
}, className)}
|
||||
>
|
||||
{children}
|
||||
</main>
|
||||
);
|
||||
|
||||
const Aside = ({ children }) => (
|
||||
const Aside: React.FC = ({ children }) => (
|
||||
<aside className='hidden xl:block xl:col-span-3'>
|
||||
<div className='sticky top-20 space-y-6'>
|
||||
<StickyBox offsetTop={80} className='space-y-6 pb-4' >
|
||||
{children}
|
||||
</div>
|
||||
</StickyBox>
|
||||
</aside>
|
||||
);
|
||||
|
||||
Layout.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
Sidebar.propTypes = {
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
Main.propTypes = {
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
Aside.propTypes = {
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
Layout.Sidebar = Sidebar;
|
||||
// @ts-ignore
|
||||
Layout.Main = Main;
|
||||
// @ts-ignore
|
||||
Layout.Aside = Aside;
|
||||
|
||||
export default Layout;
|
|
@ -261,7 +261,7 @@ class RegistrationForm extends ImmutablePureComponent {
|
|||
const isLoading = this.state.captchaLoading || this.state.submissionLoading;
|
||||
|
||||
return (
|
||||
<SimpleForm onSubmit={this.onSubmit}>
|
||||
<SimpleForm onSubmit={this.onSubmit} data-testid='registrations-open'>
|
||||
<fieldset disabled={isLoading}>
|
||||
<div className='simple_form__overlay-area'>
|
||||
<div className='fields-group'>
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import LandingPage from '..';
|
||||
import { INSTANCE_REMEMBER_SUCCESS } from '../../../actions/instance';
|
||||
import { PEPE_FETCH_INSTANCE_SUCCESS } from '../../../actions/verification';
|
||||
import { render, screen, rootReducer, applyActions } from '../../../jest/test-helpers';
|
||||
|
||||
describe('<LandingPage />', () => {
|
||||
it('renders a RegistrationForm for an open Pleroma instance', () => {
|
||||
|
||||
const state = rootReducer(undefined, {
|
||||
type: INSTANCE_REMEMBER_SUCCESS,
|
||||
instance: {
|
||||
version: '2.7.2 (compatible; Pleroma 2.3.0)',
|
||||
registrations: true,
|
||||
},
|
||||
});
|
||||
|
||||
render(<LandingPage />, null, state);
|
||||
|
||||
expect(screen.queryByTestId('registrations-open')).toBeInTheDocument();
|
||||
expect(screen.queryByTestId('registrations-closed')).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId('registrations-pepe')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders "closed" message for a closed Pleroma instance', () => {
|
||||
|
||||
const state = rootReducer(undefined, {
|
||||
type: INSTANCE_REMEMBER_SUCCESS,
|
||||
instance: {
|
||||
version: '2.7.2 (compatible; Pleroma 2.3.0)',
|
||||
registrations: false,
|
||||
},
|
||||
});
|
||||
|
||||
render(<LandingPage />, null, state);
|
||||
|
||||
expect(screen.queryByTestId('registrations-closed')).toBeInTheDocument();
|
||||
expect(screen.queryByTestId('registrations-open')).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId('registrations-pepe')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders Pepe flow for an open Truth Social instance', () => {
|
||||
|
||||
const state = applyActions(undefined, [{
|
||||
type: INSTANCE_REMEMBER_SUCCESS,
|
||||
instance: {
|
||||
version: '3.4.1 (compatible; TruthSocial 1.0.0)',
|
||||
registrations: false,
|
||||
},
|
||||
}, {
|
||||
type: PEPE_FETCH_INSTANCE_SUCCESS,
|
||||
instance: {
|
||||
registrations: true,
|
||||
},
|
||||
}], rootReducer);
|
||||
|
||||
render(<LandingPage />, null, state);
|
||||
|
||||
expect(screen.queryByTestId('registrations-pepe')).toBeInTheDocument();
|
||||
expect(screen.queryByTestId('registrations-open')).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId('registrations-closed')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders "closed" message for a Truth Social instance with Pepe closed', () => {
|
||||
|
||||
const state = applyActions(undefined, [{
|
||||
type: INSTANCE_REMEMBER_SUCCESS,
|
||||
instance: {
|
||||
version: '3.4.1 (compatible; TruthSocial 1.0.0)',
|
||||
registrations: false,
|
||||
},
|
||||
}, {
|
||||
type: PEPE_FETCH_INSTANCE_SUCCESS,
|
||||
instance: {
|
||||
registrations: false,
|
||||
},
|
||||
}], rootReducer);
|
||||
|
||||
render(<LandingPage />, null, state);
|
||||
|
||||
expect(screen.queryByTestId('registrations-closed')).toBeInTheDocument();
|
||||
expect(screen.queryByTestId('registrations-pepe')).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId('registrations-open')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
|
@ -1,18 +1,21 @@
|
|||
import * as React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import RegistrationForm from 'soapbox/features/auth_login/components/registration_form';
|
||||
import { useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||
|
||||
import { Button, Card, CardBody, Stack, Text } from '../../components/ui';
|
||||
|
||||
const LandingPage = () => {
|
||||
const instance = useSelector((state) => state.get('instance'));
|
||||
const isOpen = useSelector(state => state.getIn(['verification', 'instance', 'registrations'], false) === true);
|
||||
const features = useFeatures();
|
||||
const instance = useAppSelector((state) => state.instance);
|
||||
const pepeOpen = useAppSelector(state => state.verification.getIn(['instance', 'registrations'], false) === true);
|
||||
|
||||
/** Registrations are closed */
|
||||
const renderClosed = () => {
|
||||
return (
|
||||
<Stack space={3}>
|
||||
<Stack space={3} data-testid='registrations-closed'>
|
||||
<Text size='xl' weight='bold' align='center'>
|
||||
<FormattedMessage
|
||||
id='registration.closed_title'
|
||||
|
@ -30,6 +33,38 @@ const LandingPage = () => {
|
|||
);
|
||||
};
|
||||
|
||||
/** Mastodon API registrations are open */
|
||||
const renderOpen = () => {
|
||||
return <RegistrationForm />;
|
||||
};
|
||||
|
||||
/** Pepe API registrations are open */
|
||||
const renderPepe = () => {
|
||||
return (
|
||||
<Stack space={3} data-testid='registrations-pepe'>
|
||||
<VerificationBadge className='h-16 w-16 mx-auto' />
|
||||
|
||||
<Stack>
|
||||
<Text size='2xl' weight='bold' align='center'>Let's get started!</Text>
|
||||
<Text theme='muted' align='center'>Social Media Without Discrimination</Text>
|
||||
</Stack>
|
||||
|
||||
<Button to='/auth/verify' theme='primary' block>Create an account</Button>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
// Render registration flow depending on features
|
||||
const renderBody = () => {
|
||||
if (features.pepe && pepeOpen) {
|
||||
return renderPepe();
|
||||
} else if (instance.registrations) {
|
||||
return renderOpen();
|
||||
} else {
|
||||
return renderClosed();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<main className='mt-16 sm:mt-24'>
|
||||
<div className='mx-auto max-w-7xl'>
|
||||
|
@ -49,18 +84,7 @@ const LandingPage = () => {
|
|||
<div className='hidden lg:block sm:mt-24 lg:mt-0 lg:col-span-6'>
|
||||
<Card size='xl' variant='rounded' className='sm:max-w-md sm:w-full sm:mx-auto'>
|
||||
<CardBody>
|
||||
{isOpen ? (
|
||||
<Stack space={3}>
|
||||
<VerificationBadge className='h-16 w-16 mx-auto' />
|
||||
|
||||
<Stack>
|
||||
<Text size='2xl' weight='bold' align='center'>Let's get started!</Text>
|
||||
<Text theme='muted' align='center'>Social Media Without Discrimination</Text>
|
||||
</Stack>
|
||||
|
||||
<Button to='/auth/verify' theme='primary' block>Create an account</Button>
|
||||
</Stack>
|
||||
) : renderClosed()}
|
||||
{renderBody()}
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
|
@ -69,4 +69,5 @@ export {
|
|||
mockStore,
|
||||
applyActions,
|
||||
rootState,
|
||||
rootReducer,
|
||||
};
|
||||
|
|
|
@ -109,4 +109,22 @@ describe('getFeatures', () => {
|
|||
expect(features.focalPoint).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pepe', () => {
|
||||
it('is true for Truth Social', () => {
|
||||
const instance = InstanceRecord({
|
||||
version: '3.4.1 (compatible; TruthSocial 1.0.0)',
|
||||
});
|
||||
const features = getFeatures(instance);
|
||||
expect(features.pepe).toBe(true);
|
||||
});
|
||||
|
||||
it('is false for Pleroma', () => {
|
||||
const instance = InstanceRecord({
|
||||
version: '2.7.2 (compatible; Pleroma 2.3.0)',
|
||||
});
|
||||
const features = getFeatures(instance);
|
||||
expect(features.pepe).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -130,6 +130,7 @@ const getInstanceFeatures = (instance: Instance) => {
|
|||
]),
|
||||
trendingTruths: v.software === TRUTHSOCIAL,
|
||||
trendingStatuses: v.software === MASTODON && gte(v.compatVersion, '3.5.0'),
|
||||
pepe: v.software === TRUTHSOCIAL,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -35,8 +35,11 @@ module.exports = {
|
|||
'testMatch': ['**/*/__tests__/**/?(*.|*-)+(test).(ts|js)?(x)'],
|
||||
'testEnvironment': 'jsdom',
|
||||
'transformIgnorePatterns': [
|
||||
// FIXME: react-sticky-box doesn't provide a CJS build, so transform it for now
|
||||
// https://github.com/codecks-io/react-sticky-box/issues/79
|
||||
`/node_modules/(?!(react-sticky-box|.+\\.(${ASSET_EXTS})))`,
|
||||
// Ignore node_modules, except static assets
|
||||
`/node_modules/(?!.+\\.(${ASSET_EXTS}))`,
|
||||
// `/node_modules/(?!.+\\.(${ASSET_EXTS}))`,
|
||||
],
|
||||
'transform': {
|
||||
'\\.[jt]sx?$': 'babel-jest',
|
||||
|
|
|
@ -164,7 +164,7 @@
|
|||
"react-router-scroll-4": "^1.0.0-beta.1",
|
||||
"react-simple-pull-to-refresh": "^1.3.0",
|
||||
"react-sparklines": "^1.7.0",
|
||||
"react-stickynode": "^4.0.0",
|
||||
"react-sticky-box": "^1.0.2",
|
||||
"react-swipeable-views": "^0.14.0",
|
||||
"react-textarea-autosize": "^8.3.3",
|
||||
"react-toggle": "^4.0.1",
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"typeRoots": [ "./types", "./node_modules/@types"]
|
||||
},
|
||||
"exclude": ["node_modules", "types", "**/*.test.*", "**/__mocks__/*", "**/__tests__/*"]
|
||||
|
|
44
yarn.lock
44
yarn.lock
|
@ -3444,7 +3444,7 @@ cjs-module-lexer@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
|
||||
integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
|
||||
|
||||
classnames@^2.0.0, classnames@^2.2.5, classnames@^2.2.6:
|
||||
classnames@^2.2.5, classnames@^2.2.6:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
|
||||
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
|
||||
|
@ -3687,7 +3687,7 @@ core-js@^2.4.0:
|
|||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
core-js@^3.1.3, core-js@^3.15.2, core-js@^3.6.5:
|
||||
core-js@^3.1.3, core-js@^3.15.2:
|
||||
version "3.18.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.0.tgz#9af3f4a6df9ba3428a3fb1b171f1503b3f40cc49"
|
||||
integrity sha512-WJeQqq6jOYgVgg4NrXKL0KLQhi0CT4ZOCvFL+3CQ5o7I6J8HkT5wd53EadMfqTDp1so/MT1J+w2ujhWcCJtN7w==
|
||||
|
@ -4806,11 +4806,6 @@ etag@~1.8.1:
|
|||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||
|
||||
eventemitter3@^3.0.0:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
|
||||
integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
|
||||
|
||||
eventemitter3@^4.0.0:
|
||||
version "4.0.7"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||
|
@ -8625,7 +8620,7 @@ quote@^0.4.0:
|
|||
resolved "https://registry.yarnpkg.com/quote/-/quote-0.4.0.tgz#10839217f6c1362b89194044d29b233fd7f32f01"
|
||||
integrity sha1-EIOSF/bBNiuJGUBE0psjP9fzLwE=
|
||||
|
||||
raf@^3.0.0, raf@^3.1.0, raf@^3.4.1:
|
||||
raf@^3.1.0, raf@^3.4.1:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
||||
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
||||
|
@ -8910,16 +8905,12 @@ react-sparklines@^1.7.0:
|
|||
dependencies:
|
||||
prop-types "^15.5.10"
|
||||
|
||||
react-stickynode@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-stickynode/-/react-stickynode-4.0.0.tgz#ca1deeda866aeace3d522d01eb868f286cdb49d1"
|
||||
integrity sha512-H6Ae6l8soAc188eFAmE4CGJz3oidQa88jNO/fnJWjpFw4DwGRS6boL9gHNE4DCvbMPgek1AAP85pUPIEKUMgtw==
|
||||
react-sticky-box@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-sticky-box/-/react-sticky-box-1.0.2.tgz#7e72a0f237bdf8270cec9254337f49519a411174"
|
||||
integrity sha512-Kyvtppdtv1KqJyNU4DtrSMI0unyQRgtraZvVQ0GAazVbYiTsIVpyhpr+5R0Aavzu4uJNSe1awj2rk/qI7i6Zfw==
|
||||
dependencies:
|
||||
classnames "^2.0.0"
|
||||
core-js "^3.6.5"
|
||||
prop-types "^15.6.0"
|
||||
shallowequal "^1.0.0"
|
||||
subscribe-ui-event "^2.0.6"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
|
||||
react-swipeable-views-core@^0.14.0:
|
||||
version "0.14.0"
|
||||
|
@ -9240,6 +9231,11 @@ reselect@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
|
||||
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
|
||||
|
||||
resize-observer-polyfill@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
||||
|
||||
resolve-cwd@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
|
||||
|
@ -9544,11 +9540,6 @@ shallow-equal@^1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
|
||||
integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==
|
||||
|
||||
shallowequal@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
|
||||
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
|
||||
|
||||
shebang-command@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
||||
|
@ -9987,15 +9978,6 @@ stylelint@^13.7.2:
|
|||
v8-compile-cache "^2.3.0"
|
||||
write-file-atomic "^3.0.3"
|
||||
|
||||
subscribe-ui-event@^2.0.6:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/subscribe-ui-event/-/subscribe-ui-event-2.0.7.tgz#8d18b6339c35b25246a5335775573f0e5dc461f8"
|
||||
integrity sha512-Acrtf9XXl6lpyHAWYeRD1xTPUQHDERfL4GHeNuYAtZMc4Z8Us2iDBP0Fn3xiRvkQ1FO+hx+qRLmPEwiZxp7FDQ==
|
||||
dependencies:
|
||||
eventemitter3 "^3.0.0"
|
||||
lodash "^4.17.15"
|
||||
raf "^3.0.0"
|
||||
|
||||
substring-trie@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/substring-trie/-/substring-trie-1.0.2.tgz#7b42592391628b4f2cb17365c6cce4257c7b7af5"
|
||||
|
|
Ładowanie…
Reference in New Issue