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

removed profile sidebar completely

This commit is contained in:
Fedor Katurov 2022-08-12 13:50:35 +07:00
parent fc10dd686b
commit 4a29e11079
20 changed files with 97 additions and 190 deletions

View file

@ -1,6 +1,6 @@
# NEXT_PUBLIC_API_HOST=https://pig.staging.vault48.org/ NEXT_PUBLIC_API_HOST=https://pig.staging.vault48.org/
# NEXT_PUBLIC_REMOTE_CURRENT=https://pig.staging.vault48.org/static/ NEXT_PUBLIC_REMOTE_CURRENT=https://pig.staging.vault48.org/static/
NEXT_PUBLIC_API_HOST=http://localhost:8888/ # NEXT_PUBLIC_API_HOST=http://localhost:8888/
NEXT_PUBLIC_REMOTE_CURRENT=http://localhost:8888/static/ # NEXT_PUBLIC_REMOTE_CURRENT=http://localhost:8888/static/
# NEXT_PUBLIC_API_HOST=https://pig.vault48.org/ # NEXT_PUBLIC_API_HOST=https://pig.vault48.org/
# NEXT_PUBLIC_REMOTE_CURRENT=https://pig.vault48.org/static/ # NEXT_PUBLIC_REMOTE_CURRENT=https://pig.vault48.org/static/

4
.gitignore vendored
View file

@ -6,4 +6,6 @@
/.next /.next
/.vscode /.vscode
/.history /.history
.DS_Store .DS_Store
/tsconfig.tsbuildinfo
.env.local

View file

@ -1,13 +1,21 @@
import React, { DetailedHTMLProps, FC, HTMLAttributes } from 'react'; import React, { DetailedHTMLProps, VFC, HTMLAttributes } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import styles from '~/styles/common/markdown.module.scss'; import styles from '~/styles/common/markdown.module.scss';
import { formatText } from '~/utils/dom';
interface IProps extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> {} interface IProps
extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
children?: string;
}
const Markdown: FC<IProps> = ({ className, ...props }) => ( const Markdown: VFC<IProps> = ({ className, children = '', ...props }) => (
<div className={classNames(styles.wrapper, className)} {...props} /> <div
className={classNames(styles.wrapper, className)}
{...props}
dangerouslySetInnerHTML={{ __html: formatText(children) }}
/>
); );
export { Markdown }; export { Markdown };

View file

@ -8,7 +8,6 @@ import { DivProps } from '~/utils/types';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
interface Props extends DivProps { interface Props extends DivProps {
children: string; children: string;
heading: string | ReactElement; heading: string | ReactElement;
@ -17,10 +16,7 @@ interface Props extends DivProps {
const FlowCellText: FC<Props> = ({ children, heading, ...rest }) => ( const FlowCellText: FC<Props> = ({ children, heading, ...rest }) => (
<div {...rest} className={classNames(styles.text, rest.className)}> <div {...rest} className={classNames(styles.text, rest.className)}>
{heading && <div className={styles.heading}>{heading}</div>} {heading && <div className={styles.heading}>{heading}</div>}
<Markdown <Markdown className={styles.description}>{formatText(children)}</Markdown>
className={styles.description}
dangerouslySetInnerHTML={{ __html: formatText(children) }}
/>
</div> </div>
); );

View file

@ -20,11 +20,9 @@ const LabDescription: FC<INodeComponentProps> = ({ node, isLoading }) => {
<Paragraph /> <Paragraph />
</div> </div>
) : ( ) : (
<Markdown <Markdown className={styles.wrap} onClick={onClick}>
className={styles.wrap} {formatText(node.description)}
dangerouslySetInnerHTML={{ __html: formatText(node.description) }} </Markdown>
onClick={onClick}
/>
); );
}; };

View file

@ -10,9 +10,10 @@ import { path } from '~/utils/ramda';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
const LabText: FC<INodeComponentProps> = ({ node, isLoading }) => { const LabText: FC<INodeComponentProps> = ({ node, isLoading }) => {
const content = useMemo(() => formatTextParagraphs(path(['blocks', 0, 'text'], node) || ''), [ const content = useMemo(
node, () => formatTextParagraphs(path(['blocks', 0, 'text'], node) || ''),
]); [node],
);
const onClick = useGotoNode(node.id); const onClick = useGotoNode(node.id);
@ -21,11 +22,9 @@ const LabText: FC<INodeComponentProps> = ({ node, isLoading }) => {
<Paragraph lines={5} /> <Paragraph lines={5} />
</div> </div>
) : ( ) : (
<Markdown <Markdown className={styles.wrap} onClick={onClick}>
dangerouslySetInnerHTML={{ __html: content }} {content}
className={styles.wrap} </Markdown>
onClick={onClick}
/>
); );
}; };

View file

@ -3,7 +3,6 @@ import React, { FC, useCallback } from 'react';
import { Avatar } from '~/components/common/Avatar'; import { Avatar } from '~/components/common/Avatar';
import { useUserDescription } from '~/hooks/auth/useUserDescription'; import { useUserDescription } from '~/hooks/auth/useUserDescription';
import { INodeUser } from '~/types'; import { INodeUser } from '~/types';
import { openUserProfile } from '~/utils/user';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
@ -12,8 +11,6 @@ interface Props {
} }
const NodeAuthorBlock: FC<Props> = ({ user }) => { const NodeAuthorBlock: FC<Props> = ({ user }) => {
const onOpenProfile = useCallback(() => openUserProfile(user?.username), [user]);
const description = useUserDescription(user); const description = useUserDescription(user);
if (!user) { if (!user) {
@ -23,7 +20,7 @@ const NodeAuthorBlock: FC<Props> = ({ user }) => {
const { fullname, username, photo } = user; const { fullname, username, photo } = user;
return ( return (
<div className={styles.block} onClick={onOpenProfile}> <div className={styles.block}>
<Avatar username={username} url={photo?.url} className={styles.avatar} /> <Avatar username={username} url={photo?.url} className={styles.avatar} />
<div className={styles.info}> <div className={styles.info}>

View file

@ -1,14 +1,14 @@
import React, { useCallback, useState, VFC } from "react"; import React, { useCallback, useState, VFC } from 'react';
import { Card } from "~/components/containers/Card"; import { Card } from '~/components/containers/Card';
import { Markdown } from "~/components/containers/Markdown"; import { Markdown } from '~/components/containers/Markdown';
import { Padder } from "~/components/containers/Padder"; import { Padder } from '~/components/containers/Padder';
import { NoteMenu } from "~/components/notes/NoteMenu"; import { NoteMenu } from '~/components/notes/NoteMenu';
import { formatText, getPrettyDate } from "~/utils/dom"; import { formatText, getPrettyDate } from '~/utils/dom';
import { NoteCreationForm } from "../NoteCreationForm"; import { NoteCreationForm } from '../NoteCreationForm';
import styles from "./styles.module.scss"; import styles from './styles.module.scss';
interface NoteCardProps { interface NoteCardProps {
content: string; content: string;
@ -48,10 +48,7 @@ const NoteCard: VFC<NoteCardProps> = ({
<Padder> <Padder>
<NoteMenu onEdit={toggleEditing} onDelete={remove} /> <NoteMenu onEdit={toggleEditing} onDelete={remove} />
<Markdown <Markdown className={styles.wrap}>{formatText(content)}</Markdown>
className={styles.wrap}
dangerouslySetInnerHTML={{ __html: formatText(content) }}
/>
</Padder> </Padder>
<Padder className={styles.footer}>{getPrettyDate(createdAt)}</Padder> <Padder className={styles.footer}>{getPrettyDate(createdAt)}</Padder>

View file

@ -1,5 +1,4 @@
export enum EventMessageType { export enum EventMessageType {
OpenProfile = 'open_profile',
OAuthLogin = 'oauth_login', OAuthLogin = 'oauth_login',
OAuthProcessed = 'oauth_processed', OAuthProcessed = 'oauth_processed',
OAuthError = 'oauth_error', OAuthError = 'oauth_error',

View file

@ -4,18 +4,15 @@ import { LoadingDialog } from '~/containers/dialogs/LoadingDialog';
import { LoginDialog } from '~/containers/dialogs/LoginDialog'; import { LoginDialog } from '~/containers/dialogs/LoginDialog';
import { LoginSocialRegisterDialog } from '~/containers/dialogs/LoginSocialRegisterDialog'; import { LoginSocialRegisterDialog } from '~/containers/dialogs/LoginSocialRegisterDialog';
import { PhotoSwipe } from '~/containers/dialogs/PhotoSwipe'; import { PhotoSwipe } from '~/containers/dialogs/PhotoSwipe';
import { ProfileDialog } from '~/containers/dialogs/ProfileDialog';
import { RestorePasswordDialog } from '~/containers/dialogs/RestorePasswordDialog'; import { RestorePasswordDialog } from '~/containers/dialogs/RestorePasswordDialog';
import { RestoreRequestDialog } from '~/containers/dialogs/RestoreRequestDialog'; import { RestoreRequestDialog } from '~/containers/dialogs/RestoreRequestDialog';
import { TestDialog } from '~/containers/dialogs/TestDialog'; import { TestDialog } from '~/containers/dialogs/TestDialog';
import { ProfileSidebar } from '~/containers/sidebars/ProfileSidebar';
import { TagSidebar } from '~/containers/sidebars/TagSidebar'; import { TagSidebar } from '~/containers/sidebars/TagSidebar';
export enum Dialog { export enum Dialog {
Login = 'Login', Login = 'Login',
LoginSocialRegister = 'LoginSocialRegister', LoginSocialRegister = 'LoginSocialRegister',
Loading = 'Loading', Loading = 'Loading',
Profile = 'Profile',
RestoreRequest = 'RestoreRequest', RestoreRequest = 'RestoreRequest',
RestorePassword = 'RestorePassword', RestorePassword = 'RestorePassword',
Test = 'Test', Test = 'Test',
@ -23,7 +20,6 @@ export enum Dialog {
CreateNode = 'CreateNode', CreateNode = 'CreateNode',
EditNode = 'EditNode', EditNode = 'EditNode',
TagSidebar = 'TagNodes', TagSidebar = 'TagNodes',
ProfileSidebar = 'ProfileSidebar',
} }
export const DIALOG_CONTENT = { export const DIALOG_CONTENT = {
@ -31,12 +27,10 @@ export const DIALOG_CONTENT = {
[Dialog.LoginSocialRegister]: LoginSocialRegisterDialog, [Dialog.LoginSocialRegister]: LoginSocialRegisterDialog,
[Dialog.Loading]: LoadingDialog, [Dialog.Loading]: LoadingDialog,
[Dialog.Test]: TestDialog, [Dialog.Test]: TestDialog,
[Dialog.Profile]: ProfileDialog,
[Dialog.RestoreRequest]: RestoreRequestDialog, [Dialog.RestoreRequest]: RestoreRequestDialog,
[Dialog.RestorePassword]: RestorePasswordDialog, [Dialog.RestorePassword]: RestorePasswordDialog,
[Dialog.Photoswipe]: PhotoSwipe, [Dialog.Photoswipe]: PhotoSwipe,
[Dialog.CreateNode]: EditorCreateDialog, [Dialog.CreateNode]: EditorCreateDialog,
[Dialog.EditNode]: EditorEditDialog, [Dialog.EditNode]: EditorEditDialog,
[Dialog.TagSidebar]: TagSidebar, [Dialog.TagSidebar]: TagSidebar,
[Dialog.ProfileSidebar]: ProfileSidebar,
} as const; } as const;

View file

@ -1,39 +1,18 @@
import { FC, useCallback } from "react"; import { FC } from 'react';
import { useRouter } from "next/router"; import { Group } from '~/components/containers/Group';
import { Markdown } from '~/components/containers/Markdown';
import { Group } from "~/components/containers/Group";
import { Button } from "~/components/input/Button";
import { SidebarName } from "~/constants/sidebar";
import { URLS } from "~/constants/urls";
import { useSidebar } from "~/utils/providers/SidebarProvider";
import styles from "./styles.module.scss";
export interface BorisSuperpowersProps {} export interface BorisSuperpowersProps {}
const BorisSuperpowers: FC<BorisSuperpowersProps> = () => { const BorisSuperpowers: FC<BorisSuperpowersProps> = () => {
const { open } = useSidebar();
const openProfileSidebar = useCallback(() => {
open(SidebarName.Settings, { page: "profile" });
}, [open]);
const { push } = useRouter();
return ( return (
<Group> <Group>
<h2>Штучи, находящиеся в разработке</h2> <h2>Штучки, находящиеся в разработке</h2>
<div className={styles.grid}> <Markdown>
<Button size="mini" onClick={() => openProfileSidebar()}> {`> На данный момент в разработке нет вещей, которые можно показать.\n\n// Приходите завтра`}
Открыть </Markdown>
</Button>
<div className={styles.label}>Профиль в сайдбаре</div>
<Button size="mini" onClick={() => push(URLS.SETTINGS.BASE)}>
Открыть
</Button>
<div className={styles.label}>Профиль на отдельной странице</div>
</div>
</Group> </Group>
); );
}; };

View file

@ -1,47 +0,0 @@
import React, { FC } from 'react';
import { CoverBackdrop } from '~/components/containers/CoverBackdrop';
import { Tabs } from '~/components/dialogs/Tabs';
import { ProfileDescription } from '~/components/profile/ProfileDescription';
import { ProfileSettings } from '~/components/profile/ProfileSettings';
import { ProfileAccounts } from '~/containers/profile/ProfileAccounts';
import { ProfileInfo } from '~/containers/profile/ProfileInfo';
import { ProfileMessages } from '~/containers/profile/ProfileMessages';
import { useUser } from '~/hooks/auth/useUser';
import { useGetProfile } from '~/hooks/profile/useGetProfile';
import { DialogComponentProps } from '~/types/modal';
import { ProfileProvider } from '~/utils/providers/ProfileProvider';
import { BetterScrollDialog } from '../../../components/dialogs/BetterScrollDialog';
export interface ProfileDialogProps extends DialogComponentProps {
username: string;
}
const ProfileDialog: FC<ProfileDialogProps> = ({ username, onRequestClose }) => {
const { isLoading, profile } = useGetProfile(username);
const {
user: { id },
} = useUser();
return (
<ProfileProvider username={username}>
<Tabs>
<BetterScrollDialog
header={<ProfileInfo isOwn={profile.id === id} isLoading={isLoading} />}
backdrop={<CoverBackdrop cover={profile.cover} />}
onClose={onRequestClose}
>
<Tabs.Content>
<ProfileDescription />
<ProfileMessages />
<ProfileSettings />
<ProfileAccounts />
</Tabs.Content>
</BetterScrollDialog>
</Tabs>
</ProfileProvider>
);
};
export { ProfileDialog };

View file

@ -1,5 +0,0 @@
@import "src/styles/variables";
.messages {
padding: $gap;
}

View file

@ -26,17 +26,19 @@ const ProfilePageLeft: FC<IProps> = ({ username, profile, isLoading }) => {
/> />
<div className={styles.region}> <div className={styles.region}>
<div className={styles.name}>{isLoading ? <Placeholder /> : profile?.fullname}</div>` <div className={styles.name}>
{isLoading ? <Placeholder /> : profile?.fullname}
</div>
`
<div className={styles.username}> <div className={styles.username}>
{isLoading ? <Placeholder /> : `~${profile?.username}`} {isLoading ? <Placeholder /> : `~${profile?.username}`}
</div> </div>
</div> </div>
{!!profile?.description && ( {!!profile?.description && (
<Markdown <Markdown className={styles.description}>
className={styles.description} {formatText(profile.description)}
dangerouslySetInnerHTML={{ __html: formatText(profile.description) }} </Markdown>
/>
)} )}
</div> </div>
); );

View file

@ -35,14 +35,6 @@ export const useMessageEventReactions = () => {
void createSocialAccount(path(['data', 'payload', 'token'], event)); void createSocialAccount(path(['data', 'payload', 'token'], event));
} }
break; break;
case EventMessageType.OpenProfile:
const username: string | undefined = path(['data', 'username'], event);
if (!username) {
return;
}
showModal(Dialog.Profile, { username });
break;
default: default:
console.log('unknown message', event.data); console.log('unknown message', event.data);
} }

View file

@ -1,21 +1,21 @@
import { FC, useMemo } from "react"; import { FC, useMemo } from 'react';
import { observer } from "mobx-react-lite"; import { observer } from 'mobx-react-lite';
import { BorisGraphicStats } from "~/components/boris/BorisGraphicStats"; import { BorisGraphicStats } from '~/components/boris/BorisGraphicStats';
import { Superpower } from "~/components/boris/Superpower"; import { Superpower } from '~/components/boris/Superpower';
import { Card } from "~/components/containers/Card"; import { Card } from '~/components/containers/Card';
import { Group } from "~/components/containers/Group"; import { Group } from '~/components/containers/Group';
import { Sticky } from "~/components/containers/Sticky"; import { Sticky } from '~/components/containers/Sticky';
import { BorisComments } from "~/containers/boris/BorisComments"; import { BorisComments } from '~/containers/boris/BorisComments';
import { BorisSidebar } from "~/containers/boris/BorisSidebar"; import { BorisSidebar } from '~/containers/boris/BorisSidebar';
import { BorisSuperPowersSSR } from "~/containers/boris/BorisSuperpowers/ssr"; import { BorisSuperPowersSSR } from '~/containers/boris/BorisSuperpowers/ssr';
import { Container } from "~/containers/main/Container"; import { Container } from '~/containers/main/Container';
import { SidebarRouter } from "~/containers/main/SidebarRouter"; import { SidebarRouter } from '~/containers/main/SidebarRouter';
import { BorisUsageStats } from "~/types/boris"; import { BorisUsageStats } from '~/types/boris';
import { useAuthProvider } from "~/utils/providers/AuthProvider"; import { useAuthProvider } from '~/utils/providers/AuthProvider';
import styles from "./styles.module.scss"; import styles from './styles.module.scss';
type IProps = { type IProps = {
title: string; title: string;
@ -50,9 +50,11 @@ const BorisLayout: FC<IProps> = observer(({ title, stats, isLoadingStats }) => {
<div className={styles.container}> <div className={styles.container}>
<Card className={styles.content}> <Card className={styles.content}>
<Group> <Group>
<Superpower> <div>
<BorisSuperPowersSSR /> <Superpower>
</Superpower> <BorisSuperPowersSSR />
</Superpower>
</div>
<BorisGraphicStats <BorisGraphicStats
totalComments={stats.backend.comments.total} totalComments={stats.backend.comments.total}

View file

@ -1,4 +1,4 @@
@import "src/styles/variables"; @import 'src/styles/variables';
@import 'photoswipe/dist/photoswipe'; @import 'photoswipe/dist/photoswipe';
@import 'photoswipe/dist/default-skin/default-skin'; @import 'photoswipe/dist/default-skin/default-skin';
@ -55,7 +55,8 @@ body {
color: #555555; color: #555555;
} }
.todo, .done { .todo,
.done {
color: #333333; color: #333333;
border-radius: 3px; border-radius: 3px;
padding: 0 2px; padding: 0 2px;
@ -76,12 +77,8 @@ h2 {
} }
.username { .username {
background: transparentize($color: #000000, $amount: 0.8);
padding: 2px 4px;
border-radius: 4px;
cursor: pointer;
color: $wisegreen; color: $wisegreen;
font-weight: bold; font-weight: 600;
} }
a { a {
@ -129,12 +126,16 @@ button {
outline: none; outline: none;
} }
h3, h2, h1 { h3,
h2,
h1 {
color: white; color: white;
font-weight: 800; font-weight: 800;
} }
h6, h5, h4 { h6,
h5,
h4 {
color: white; color: white;
font-weight: 600; font-weight: 600;
} }
@ -177,4 +178,4 @@ p {
small { small {
font-size: 0.8em; font-size: 0.8em;
} }

View file

@ -9,22 +9,20 @@ import { stripHTMLTags } from '~/utils/stripHTMLTags';
export const formatTextSanitizeYoutube = (text: string): string => export const formatTextSanitizeYoutube = (text: string): string =>
text.replace( text.replace(
/(https?:\/\/(www\.)?(youtube\.com|youtu\.be)\/(watch)?(\?v=)?[\w\-&=]+)/gim, /(https?:\/\/(www\.)?(youtube\.com|youtu\.be)\/(watch)?(\?v=)?[\w\-&=]+)/gim,
'\n$1\n' '\n$1\n',
); );
/** /**
* Removes HTML tags * Removes HTML tags
*/ */
export const formatTextSanitizeTags = (text: string): string => stripHTMLTags(text); export const formatTextSanitizeTags = (text: string): string =>
stripHTMLTags(text);
/** /**
* Returns clickable usernames * Returns clickable usernames
*/ */
export const formatTextClickableUsernames = (text: string): string => export const formatTextClickableUsernames = (text: string): string =>
text.replace( text.replace(/~([\wа-яА-Я-]+)/giu, `<span class="username">~$1</span>`);
/~([\wа-яА-Я-]+)/giu,
`<span class="username" onClick="window.postMessage({ type: '${EventMessageType.OpenProfile}', username: '$1'});">~$1</span>`
);
/** /**
* Makes gray comments * Makes gray comments
@ -41,10 +39,13 @@ export const formatTextComments = (text: string): string =>
*/ */
export const formatTextTodos = (text: string): string => export const formatTextTodos = (text: string): string =>
text text
.replace(/\/\/\s*(todo|туду):?\s*([^\n]+)/gim, '// <span class="todo">$1</span> $2') .replace(
/\/\/\s*(todo|туду):?\s*([^\n]+)/gim,
'// <span class="todo">$1</span> $2',
)
.replace( .replace(
/\/\/\s*(done|сделано|сделал|готово|fixed|пофикшено|фиксед):?\s*([^\n]+)/gim, /\/\/\s*(done|сделано|сделал|готово|fixed|пофикшено|фиксед):?\s*([^\n]+)/gim,
'// <span class="done">$1</span> $2' '// <span class="done">$1</span> $2',
); );
/** /**
@ -56,7 +57,8 @@ export const formatExclamations = (text: string): string =>
/** /**
* Replaces -- with dash * Replaces -- with dash
*/ */
export const formatTextDash = (text: string): string => text.replace(' -- ', ' — '); export const formatTextDash = (text: string): string =>
text.replace(' -- ', ' — ');
/** /**
* Formats with markdown * Formats with markdown

View file

@ -1,9 +0,0 @@
import { EventMessageType } from '~/constants/events';
export const openUserProfile = (username?: string) => {
if (!username) {
return;
}
window.postMessage({ type: EventMessageType.OpenProfile, username }, '*');
};

File diff suppressed because one or more lines are too long