1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 04:46:40 +07:00

#23 added superpowers ui tab

This commit is contained in:
Fedor Katurov 2021-03-19 17:00:26 +07:00
parent c939dcbce8
commit b1f019ebae
15 changed files with 162 additions and 42 deletions

View file

@ -8,6 +8,7 @@
"@testing-library/react": "^11.1.0", "@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^12.1.10",
"@tippy.js/react": "^3.1.1", "@tippy.js/react": "^3.1.1",
"@types/react-router-dom": "^5.1.7",
"autosize": "^4.0.2", "autosize": "^4.0.2",
"axios": "^0.21.1", "axios": "^0.21.1",
"body-scroll-lock": "^2.6.4", "body-scroll-lock": "^2.6.4",

View file

@ -21,7 +21,7 @@ const BorisComments: FC<IProps> = ({ isLoadingComments, node, commentCount, comm
const user = useShallowSelect(selectAuthUser); const user = useShallowSelect(selectAuthUser);
return ( return (
<Card className={styles.content}> <>
<Group className={styles.grid}> <Group className={styles.grid}>
{user.is_user && <NodeCommentForm isBefore nodeId={node.id} />} {user.is_user && <NodeCommentForm isBefore nodeId={node.id} />}
@ -33,7 +33,7 @@ const BorisComments: FC<IProps> = ({ isLoadingComments, node, commentCount, comm
</Group> </Group>
<Footer /> <Footer />
</Card> </>
); );
}; };

View file

@ -4,7 +4,7 @@
flex: 4; flex: 4;
z-index: 2; z-index: 2;
border-radius: $radius; border-radius: $radius;
padding: 0; padding: $gap;
background: $node_bg; background: $node_bg;
box-shadow: inset transparentize(mix($wisegreen, white, 60%), 0.6) 0 1px; box-shadow: inset transparentize(mix($wisegreen, white, 60%), 0.6) 0 1px;

View file

@ -1,9 +1,12 @@
@import "~/styles/variables.scss";
.card { .card {
flex: 3; flex: 3;
align-self: stretch; align-self: stretch;
position: relative; position: relative;
z-index: 1; z-index: 1;
padding: 20px 30px; padding: 20px 30px;
background-color: lighten($content_bg, 4%);
} }
.sample { .sample {

View file

@ -0,0 +1,16 @@
import React, { FC, MouseEventHandler } from 'react';
import classNames from 'classnames';
import styles from './styles.module.scss';
interface IProps {
active?: boolean;
onClick?: MouseEventHandler<any>;
}
const Tab: FC<IProps> = ({ active, onClick, children }) => (
<div className={classNames(styles.tab, { [styles.active]: active })} onClick={onClick}>
{children}
</div>
);
export { Tab };

View file

@ -0,0 +1,20 @@
@import "src/styles/variables";
.tab {
@include outer_shadow();
padding: $gap;
margin-right: $gap;
border-radius: $radius $radius 0 0;
font: $font_14_semibold;
text-transform: uppercase;
cursor: pointer;
background-color: $content_bg;
color: white;
text-decoration: none;
border: none;
&.active {
background: lighten($content_bg, 4%);
}
}

View file

@ -0,0 +1,12 @@
import React, { FC, useCallback } from 'react';
import styles from './styles.module.scss';
import classNames from 'classnames';
import { IAuthState } from '~/redux/auth/types';
interface IProps {}
const Tabs: FC<IProps> = ({ children }) => {
return <div className={styles.wrap}>{children}</div>;
};
export { Tabs };

View file

@ -0,0 +1,9 @@
@import "src/styles/variables";
.wrap {
display: flex;
align-items: flex-start;
justify-content: flex-start;
margin: $gap * 2 0 0 0;
padding: 0 $gap;
}

View file

@ -12,7 +12,7 @@ type IProps = RouteComponentProps & {
type CellSize = 'small' | 'medium' | 'large'; type CellSize = 'small' | 'medium' | 'large';
const getTitleLetters = (title: string): string => { const getTitleLetters = (title?: string): string => {
const words = (title && title.split(' ')) || []; const words = (title && title.split(' ')) || [];
if (!words.length) return ''; if (!words.length) return '';

View file

@ -17,9 +17,14 @@ import { Container } from '~/containers/main/Container';
import StickyBox from 'react-sticky-box/dist/esnext'; import StickyBox from 'react-sticky-box/dist/esnext';
import { BorisComments } from '~/components/boris/BorisComments'; import { BorisComments } from '~/components/boris/BorisComments';
import { URLS } from '~/constants/urls'; import { URLS } from '~/constants/urls';
import { Route, Switch } from 'react-router-dom'; import { Route, Switch, Link } from 'react-router-dom';
import { BorisUIDemo } from '~/components/boris/BorisUIDemo'; import { BorisUIDemo } from '~/components/boris/BorisUIDemo';
import { BorisSuperpowers } from '~/components/boris/BorisSuperpowers'; import { BorisSuperpowers } from '~/components/boris/BorisSuperpowers';
import { Superpower } from '~/components/boris/Superpower';
import { Tabs } from '~/components/dialogs/Tabs';
import { Tab } from '~/components/dialogs/Tab';
import { useHistory, useLocation } from 'react-router';
import { Card } from '~/components/containers/Card';
type IProps = {}; type IProps = {};
@ -63,6 +68,9 @@ const BorisLayout: FC<IProps> = () => {
[dispatch] [dispatch]
); );
const history = useHistory();
const location = useLocation();
return ( return (
<Container> <Container>
<div className={styles.wrap}> <div className={styles.wrap}>
@ -77,18 +85,38 @@ const BorisLayout: FC<IProps> = () => {
</div> </div>
<div className={styles.container}> <div className={styles.container}>
{ <Card className={styles.content}>
<Switch> <Superpower>
<Route path={`${URLS.BORIS}/ui`} component={BorisUIDemo} /> <Tabs>
<Tab
active={location.pathname === URLS.BORIS}
onClick={() => history.push(URLS.BORIS)}
>
Комментарии
</Tab>
<BorisComments <Tab
isLoadingComments={node.is_loading_comments} active={location.pathname === `${URLS.BORIS}/ui`}
commentCount={node.comment_count} onClick={() => history.push(`${URLS.BORIS}/ui`)}
node={node.current} >
comments={node.comments} UI Demo
/> </Tab>
</Switch> </Tabs>
} </Superpower>
{
<Switch>
<Route path={`${URLS.BORIS}/ui`} component={BorisUIDemo} />
<BorisComments
isLoadingComments={node.is_loading_comments}
commentCount={node.comment_count}
node={node.current}
comments={node.comments}
/>
</Switch>
}
</Card>
<Group className={styles.stats}> <Group className={styles.stats}>
<StickyBox className={styles.sticky} offsetTop={72} offsetBottom={10}> <StickyBox className={styles.sticky} offsetTop={72} offsetBottom={10}>

View file

@ -20,7 +20,7 @@
width: 100%; width: 100%;
height: 100vh; height: 100vh;
overflow: hidden; overflow: hidden;
background: 50% 0% no-repeat url('../../../sprites/boris_bg.svg'); background: 50% 0 no-repeat url('../../../sprites/boris_bg.svg');
background-size: cover; background-size: cover;
} }
@ -151,3 +151,8 @@
} }
} }
} }
.content {
position: relative;
z-index: 1;
}

View file

@ -29,7 +29,9 @@ const ProfileLayoutUnconnected: FC<IProps> = ({ history, nodeSetCoverImage }) =>
useEffect(() => { useEffect(() => {
if (user && user.id && user.cover) { if (user && user.id && user.cover) {
nodeSetCoverImage(user.cover); nodeSetCoverImage(user.cover);
return () => nodeSetCoverImage(null); return () => {
nodeSetCoverImage(undefined);
};
} }
}, [user]); }, [user]);

View file

@ -2,6 +2,8 @@ import React, { FC, useCallback } from 'react';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import classNames from 'classnames'; import classNames from 'classnames';
import { IAuthState } from '~/redux/auth/types'; import { IAuthState } from '~/redux/auth/types';
import { Tabs } from '~/components/dialogs/Tabs';
import { Tab } from '~/components/dialogs/Tab';
interface IProps { interface IProps {
tab: string; tab: string;
@ -19,30 +21,20 @@ const ProfileTabs: FC<IProps> = ({ tab, is_own, setTab }) => {
); );
return ( return (
<div className={styles.wrap}> <Tabs>
<div <Tab active={tab === 'profile'} onClick={changeTab('profile')}>
className={classNames(styles.tab, { [styles.active]: tab === 'profile' })}
onClick={changeTab('profile')}
>
Профиль Профиль
</div> </Tab>
<div
className={classNames(styles.tab, { [styles.active]: tab === 'messages' })} <Tab active={tab === 'messages'} onClick={changeTab('messages')}>
onClick={changeTab('messages')}
>
Сообщения Сообщения
</div> </Tab>
{is_own && ( {is_own && (
<> <Tab active={tab === 'settings'} onClick={changeTab('settings')}>
<div Настройки
className={classNames(styles.tab, { [styles.active]: tab === 'settings' })} </Tab>
onClick={changeTab('settings')}
>
Настройки
</div>
</>
)} )}
</div> </Tabs>
); );
}; };

View file

@ -10,13 +10,23 @@ function* onPathChange({
}, },
}: LocationChangeAction) { }: LocationChangeAction) {
if (pathname.match(/^\/~([\wа-яА-Я]+)/)) { if (pathname.match(/^\/~([\wа-яА-Я]+)/)) {
const [, username] = pathname.match(/^\/~([\wа-яА-Я]+)/); const match = pathname.match(/^\/~([\wа-яА-Я]+)/);
return yield put(authOpenProfile(username));
if (!match || !match.length || !match[1]) {
return;
}
return yield put(authOpenProfile(match[1]));
} }
if (pathname.match(/^\/restore\/([\w\-]+)/)) { if (pathname.match(/^\/restore\/([\w\-]+)/)) {
const [, code] = pathname.match(/^\/restore\/([\w\-]+)/); const match = pathname.match(/^\/restore\/([\w\-]+)/);
return yield put(authShowRestoreModal(code));
if (!match || !match.length || !match[1]) {
return;
}
return yield put(authShowRestoreModal(match[1]));
} }
} }

View file

@ -1658,6 +1658,11 @@
"@types/minimatch" "*" "@types/minimatch" "*"
"@types/node" "*" "@types/node" "*"
"@types/history@*":
version "4.7.8"
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934"
integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==
"@types/hoist-non-react-statics@^3.3.0": "@types/hoist-non-react-statics@^3.3.0":
version "3.3.1" version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
@ -1763,6 +1768,23 @@
hoist-non-react-statics "^3.3.0" hoist-non-react-statics "^3.3.0"
redux "^4.0.0" redux "^4.0.0"
"@types/react-router-dom@^5.1.7":
version "5.1.7"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.7.tgz#a126d9ea76079ffbbdb0d9225073eb5797ab7271"
integrity sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react-router" "*"
"@types/react-router@*":
version "5.1.12"
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.12.tgz#0f300e09468e7aed86e18241c90238c18c377e51"
integrity sha512-0bhXQwHYfMeJlCh7mGhc0VJTRm0Gk+Z8T00aiP4702mDUuLs9SMhnd2DitpjWFjdOecx2UXtICK14H9iMnziGA==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react@*": "@types/react@*":
version "16.9.56" version "16.9.56"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.56.tgz#ea25847b53c5bec064933095fc366b1462e2adf0" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.56.tgz#ea25847b53c5bec064933095fc366b1462e2adf0"