mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
#23 added superpowers ui tab
This commit is contained in:
parent
c939dcbce8
commit
b1f019ebae
15 changed files with 162 additions and 42 deletions
|
@ -8,6 +8,7 @@
|
|||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
"@tippy.js/react": "^3.1.1",
|
||||
"@types/react-router-dom": "^5.1.7",
|
||||
"autosize": "^4.0.2",
|
||||
"axios": "^0.21.1",
|
||||
"body-scroll-lock": "^2.6.4",
|
||||
|
|
|
@ -21,7 +21,7 @@ const BorisComments: FC<IProps> = ({ isLoadingComments, node, commentCount, comm
|
|||
const user = useShallowSelect(selectAuthUser);
|
||||
|
||||
return (
|
||||
<Card className={styles.content}>
|
||||
<>
|
||||
<Group className={styles.grid}>
|
||||
{user.is_user && <NodeCommentForm isBefore nodeId={node.id} />}
|
||||
|
||||
|
@ -33,7 +33,7 @@ const BorisComments: FC<IProps> = ({ isLoadingComments, node, commentCount, comm
|
|||
</Group>
|
||||
|
||||
<Footer />
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
flex: 4;
|
||||
z-index: 2;
|
||||
border-radius: $radius;
|
||||
padding: 0;
|
||||
padding: $gap;
|
||||
background: $node_bg;
|
||||
box-shadow: inset transparentize(mix($wisegreen, white, 60%), 0.6) 0 1px;
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
@import "~/styles/variables.scss";
|
||||
|
||||
.card {
|
||||
flex: 3;
|
||||
align-self: stretch;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 20px 30px;
|
||||
background-color: lighten($content_bg, 4%);
|
||||
}
|
||||
|
||||
.sample {
|
||||
|
|
16
src/components/dialogs/Tab/index.tsx
Normal file
16
src/components/dialogs/Tab/index.tsx
Normal 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 };
|
20
src/components/dialogs/Tab/styles.module.scss
Normal file
20
src/components/dialogs/Tab/styles.module.scss
Normal 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%);
|
||||
}
|
||||
}
|
12
src/components/dialogs/Tabs/index.tsx
Normal file
12
src/components/dialogs/Tabs/index.tsx
Normal 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 };
|
9
src/components/dialogs/Tabs/styles.module.scss
Normal file
9
src/components/dialogs/Tabs/styles.module.scss
Normal 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;
|
||||
}
|
|
@ -12,7 +12,7 @@ type IProps = RouteComponentProps & {
|
|||
|
||||
type CellSize = 'small' | 'medium' | 'large';
|
||||
|
||||
const getTitleLetters = (title: string): string => {
|
||||
const getTitleLetters = (title?: string): string => {
|
||||
const words = (title && title.split(' ')) || [];
|
||||
|
||||
if (!words.length) return '';
|
||||
|
|
|
@ -17,9 +17,14 @@ import { Container } from '~/containers/main/Container';
|
|||
import StickyBox from 'react-sticky-box/dist/esnext';
|
||||
import { BorisComments } from '~/components/boris/BorisComments';
|
||||
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 { 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 = {};
|
||||
|
||||
|
@ -63,6 +68,9 @@ const BorisLayout: FC<IProps> = () => {
|
|||
[dispatch]
|
||||
);
|
||||
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<div className={styles.wrap}>
|
||||
|
@ -77,18 +85,38 @@ const BorisLayout: FC<IProps> = () => {
|
|||
</div>
|
||||
|
||||
<div className={styles.container}>
|
||||
{
|
||||
<Switch>
|
||||
<Route path={`${URLS.BORIS}/ui`} component={BorisUIDemo} />
|
||||
<Card className={styles.content}>
|
||||
<Superpower>
|
||||
<Tabs>
|
||||
<Tab
|
||||
active={location.pathname === URLS.BORIS}
|
||||
onClick={() => history.push(URLS.BORIS)}
|
||||
>
|
||||
Комментарии
|
||||
</Tab>
|
||||
|
||||
<BorisComments
|
||||
isLoadingComments={node.is_loading_comments}
|
||||
commentCount={node.comment_count}
|
||||
node={node.current}
|
||||
comments={node.comments}
|
||||
/>
|
||||
</Switch>
|
||||
}
|
||||
<Tab
|
||||
active={location.pathname === `${URLS.BORIS}/ui`}
|
||||
onClick={() => history.push(`${URLS.BORIS}/ui`)}
|
||||
>
|
||||
UI Demo
|
||||
</Tab>
|
||||
</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}>
|
||||
<StickyBox className={styles.sticky} offsetTop={72} offsetBottom={10}>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
width: 100%;
|
||||
height: 100vh;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -151,3 +151,8 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,9 @@ const ProfileLayoutUnconnected: FC<IProps> = ({ history, nodeSetCoverImage }) =>
|
|||
useEffect(() => {
|
||||
if (user && user.id && user.cover) {
|
||||
nodeSetCoverImage(user.cover);
|
||||
return () => nodeSetCoverImage(null);
|
||||
return () => {
|
||||
nodeSetCoverImage(undefined);
|
||||
};
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ import React, { FC, useCallback } from 'react';
|
|||
import styles from './styles.module.scss';
|
||||
import classNames from 'classnames';
|
||||
import { IAuthState } from '~/redux/auth/types';
|
||||
import { Tabs } from '~/components/dialogs/Tabs';
|
||||
import { Tab } from '~/components/dialogs/Tab';
|
||||
|
||||
interface IProps {
|
||||
tab: string;
|
||||
|
@ -19,30 +21,20 @@ const ProfileTabs: FC<IProps> = ({ tab, is_own, setTab }) => {
|
|||
);
|
||||
|
||||
return (
|
||||
<div className={styles.wrap}>
|
||||
<div
|
||||
className={classNames(styles.tab, { [styles.active]: tab === 'profile' })}
|
||||
onClick={changeTab('profile')}
|
||||
>
|
||||
<Tabs>
|
||||
<Tab active={tab === 'profile'} onClick={changeTab('profile')}>
|
||||
Профиль
|
||||
</div>
|
||||
<div
|
||||
className={classNames(styles.tab, { [styles.active]: tab === 'messages' })}
|
||||
onClick={changeTab('messages')}
|
||||
>
|
||||
</Tab>
|
||||
|
||||
<Tab active={tab === 'messages'} onClick={changeTab('messages')}>
|
||||
Сообщения
|
||||
</div>
|
||||
</Tab>
|
||||
{is_own && (
|
||||
<>
|
||||
<div
|
||||
className={classNames(styles.tab, { [styles.active]: tab === 'settings' })}
|
||||
onClick={changeTab('settings')}
|
||||
>
|
||||
Настройки
|
||||
</div>
|
||||
</>
|
||||
<Tab active={tab === 'settings'} onClick={changeTab('settings')}>
|
||||
Настройки
|
||||
</Tab>
|
||||
)}
|
||||
</div>
|
||||
</Tabs>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -10,13 +10,23 @@ function* onPathChange({
|
|||
},
|
||||
}: LocationChangeAction) {
|
||||
if (pathname.match(/^\/~([\wа-яА-Я]+)/)) {
|
||||
const [, username] = pathname.match(/^\/~([\wа-яА-Я]+)/);
|
||||
return yield put(authOpenProfile(username));
|
||||
const match = pathname.match(/^\/~([\wа-яА-Я]+)/);
|
||||
|
||||
if (!match || !match.length || !match[1]) {
|
||||
return;
|
||||
}
|
||||
|
||||
return yield put(authOpenProfile(match[1]));
|
||||
}
|
||||
|
||||
if (pathname.match(/^\/restore\/([\w\-]+)/)) {
|
||||
const [, code] = pathname.match(/^\/restore\/([\w\-]+)/);
|
||||
return yield put(authShowRestoreModal(code));
|
||||
const match = pathname.match(/^\/restore\/([\w\-]+)/);
|
||||
|
||||
if (!match || !match.length || !match[1]) {
|
||||
return;
|
||||
}
|
||||
|
||||
return yield put(authShowRestoreModal(match[1]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
22
yarn.lock
22
yarn.lock
|
@ -1658,6 +1658,11 @@
|
|||
"@types/minimatch" "*"
|
||||
"@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":
|
||||
version "3.3.1"
|
||||
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"
|
||||
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@*":
|
||||
version "16.9.56"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.56.tgz#ea25847b53c5bec064933095fc366b1462e2adf0"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue