diff --git a/package.json b/package.json index 562936cd..4a424f81 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "body-scroll-lock": "^2.6.4", "classnames": "^2.2.6", "color2k": "^1.2.4", - "connected-react-router": "^6.5.2", "date-fns": "^2.4.1", "file-loader": "^6.2.0", "flexbin": "^0.2.0", @@ -22,7 +21,8 @@ "insane": "^2.6.2", "marked": "^2.0.0", "mobx": "^6.3.10", - "mobx-react": "^7.2.1", + "mobx-persist-store": "^1.0.4", + "mobx-react-lite": "^3.2.3", "next": "^12.0.7", "node-sass": "^4.14.1", "photoswipe": "^4.1.3", @@ -35,15 +35,11 @@ "react-lazyload": "^3.2.0", "react-masonry-css": "^1.0.16", "react-popper": "^2.2.3", - "react-redux": "^7.2.2", "react-router": "^5.1.2", "react-router-dom": "^5.1.2", "react-scripts": "^5.0.0", "react-sortable-hoc": "^2.0.0", "react-sticky-box": "^0.9.3", - "redux": "^4.1.2", - "redux-persist": "^5.10.0", - "redux-saga": "^1.1.1", "sticky-sidebar": "^3.3.1", "swiper": "^6.8.4", "swr": "^1.0.1", @@ -83,7 +79,6 @@ "@types/marked": "^1.2.2", "@types/node": "^11.13.22", "@types/ramda": "^0.26.33", - "@types/react-redux": "^7.1.11", "@types/throttle-debounce": "^2.1.0", "@types/yup": "^0.29.11", "craco-alias": "^2.3.1", diff --git a/src/redux/auth/api.ts b/src/api/auth/index.ts similarity index 94% rename from src/redux/auth/api.ts rename to src/api/auth/index.ts index 0224759f..613e8adb 100644 --- a/src/redux/auth/api.ts +++ b/src/api/auth/index.ts @@ -21,7 +21,7 @@ import { ApiUpdateUserResult, ApiUserLoginRequest, ApiUserLoginResult, -} from './types'; +} from '~/api/auth/types'; export const apiUserLogin = ({ username, password }: ApiUserLoginRequest) => api @@ -41,9 +41,9 @@ export const apiAuthGetUpdates = ({ exclude_dialogs, last }: ApiAuthGetUpdatesRe export const apiUpdateUser = ({ user }: ApiUpdateUserRequest) => api.patch(API.USER.ME, user).then(cleanResult); -export const apiRequestRestoreCode = ({ field }: { field: string }) => +export const apiRequestRestoreCode = (field: string) => api - .post<{}>(API.USER.REQUEST_CODE(), { field }) + .post<{ field: string }>(API.USER.REQUEST_CODE(), { field }) .then(cleanResult); export const apiCheckRestoreCode = ({ code }: ApiCheckRestoreCodeRequest) => diff --git a/src/redux/auth/types.ts b/src/api/auth/types.ts similarity index 51% rename from src/redux/auth/types.ts rename to src/api/auth/types.ts index 652a4df5..7a0c17d5 100644 --- a/src/redux/auth/types.ts +++ b/src/api/auth/types.ts @@ -1,104 +1,16 @@ -import { IFile, INotification } from '../types'; - -export interface IToken { - access: string; - refresh: string; -} - -export interface IUser { - id: number; - username: string; - email: string; - role: string; - photo?: IFile; - cover?: IFile; - name: string; - fullname: string; - description: string; - - last_seen: string; - last_seen_messages: string; - last_seen_boris: string; - - is_activated: boolean; - is_user: boolean; -} - -export type ISocialProvider = 'vkontakte' | 'google'; - -export interface ISocialAccount { - provider: ISocialProvider; - id: string; - name: string; - photo: string; -} - -export type IAuthState = Readonly<{ - user: IUser; - token: string; - - is_tester: boolean; - - updates: { - last: string; - notifications: INotification[]; - boris_commented_at: string; - }; - - login: { - error: string; - is_loading: boolean; - is_registering: boolean; - }; - - profile: { - is_loading: boolean; - - user?: IUser; - patch_errors: Record; - - socials: { - accounts: ISocialAccount[]; - error: string; - is_loading: boolean; - }; - }; - - restore: { - code: string; - user?: Pick; - is_loading: boolean; - is_succesfull: boolean; - error: string; - }; - - register_social: { - errors: { - username: string; - password: string; - }; - error: string; - token: string; - is_loading: boolean; - }; -}>; - -export type ApiWithTokenRequest = { access: string }; +import { INotification } from '~/types'; +import { ISocialAccount, IUser } from '~/types/auth'; export type ApiUserLoginRequest = Record<'username' | 'password', string>; export type ApiUserLoginResult = { token: string; user: IUser }; - export type ApiAuthGetUserRequest = {}; export type ApiAuthGetUserResult = { user: IUser }; - export type ApiUpdateUserRequest = { user: Partial; }; export type ApiUpdateUserResult = { user: IUser; errors: Record, string> }; - export type ApiAuthGetUserProfileRequest = { username: string }; export type ApiAuthGetUserProfileResult = { user: IUser }; - export type ApiAuthGetUpdatesRequest = { exclude_dialogs: number; last: string; @@ -107,27 +19,20 @@ export type ApiAuthGetUpdatesResult = { notifications: INotification[]; boris: { commented_at: string }; }; - export type ApiCheckRestoreCodeRequest = { code: string }; export type ApiCheckRestoreCodeResult = { user: IUser }; - export type ApiRestoreCodeRequest = { code: string; password: string }; export type ApiRestoreCodeResult = { token: string; user: IUser }; - export type ApiGetSocialsResult = { accounts: ISocialAccount[] }; - export type ApiDropSocialRequest = { id: string; provider: string }; export type ApiDropSocialResult = { accounts: ISocialAccount[] }; - export type ApiAttachSocialRequest = { token: string }; export type ApiAttachSocialResult = { account: ISocialAccount }; - export type ApiLoginWithSocialRequest = { token: string; username?: string; password?: string; }; - export type ApiLoginWithSocialResult = { token: string; errors: Record; diff --git a/src/api/flow/index.ts b/src/api/flow/index.ts index fbfd3823..2a573e03 100644 --- a/src/api/flow/index.ts +++ b/src/api/flow/index.ts @@ -1,18 +1,8 @@ -import { api, cleanResult, configWithToken } from '~/utils/api'; -import { INode, IResultWithStatus } from 'src/redux/types'; +import { api, cleanResult } from '~/utils/api'; import { API } from '~/constants/api'; import { PostCellViewRequest, PostCellViewResult } from '~/types/node'; import { GetSearchResultsRequest, GetSearchResultsResult } from '~/types/flow'; -export const postNode = ({ - access, - node, -}: { - access: string; - node: INode; -}): Promise> => - api.post(API.NODE.SAVE, { node }, configWithToken(access)).then(cleanResult); - export const postCellView = ({ id, flow }: PostCellViewRequest) => api .post(API.NODE.SET_CELL_VIEW(id), { flow }) diff --git a/src/api/messages/types.ts b/src/api/messages/types.ts index 519e7057..e51d013c 100644 --- a/src/api/messages/types.ts +++ b/src/api/messages/types.ts @@ -1,4 +1,4 @@ -import { IMessage } from '~/redux/types'; +import { IMessage } from '~/types'; export type ApiGetUserMessagesRequest = { username: string; diff --git a/src/api/node/index.ts b/src/api/node/index.ts index 7370a7e6..cce95d1d 100644 --- a/src/api/node/index.ts +++ b/src/api/node/index.ts @@ -1,5 +1,5 @@ import { api, cleanResult } from '~/utils/api'; -import { IComment, INode } from '~/redux/types'; +import { IComment, INode } from '~/types'; import { API } from '~/constants/api'; import { COMMENTS_DISPLAY } from '~/constants/node'; import { diff --git a/src/api/uploads/types.ts b/src/api/uploads/types.ts index 0b6337de..58ec0a73 100644 --- a/src/api/uploads/types.ts +++ b/src/api/uploads/types.ts @@ -1,4 +1,4 @@ -import { IFile, IUploadProgressHandler } from '~/redux/types'; +import { IFile, IUploadProgressHandler } from '~/types'; import { UploadTarget, UploadType } from '~/constants/uploads'; export type ApiUploadFileRequest = { diff --git a/src/components/auth/login/LoginDialogButtons/index.tsx b/src/components/auth/login/LoginDialogButtons/index.tsx new file mode 100644 index 00000000..0f6ce91a --- /dev/null +++ b/src/components/auth/login/LoginDialogButtons/index.tsx @@ -0,0 +1,38 @@ +import React, { FC } from 'react'; +import { Button } from '~/components/input/Button'; +import { Grid } from '~/components/containers/Grid'; +import { Group } from '~/components/containers/Group'; +import styles from './styles.module.scss'; +import { OAuthProvider } from '~/types/auth'; + +interface IProps { + openOauthWindow: (provider: OAuthProvider) => void; +} + +const LoginDialogButtons: FC = ({ openOauthWindow }) => ( + + + + + + + + + +); + +export { LoginDialogButtons }; diff --git a/src/containers/dialogs/LoginDialogButtons/styles.module.scss b/src/components/auth/login/LoginDialogButtons/styles.module.scss similarity index 100% rename from src/containers/dialogs/LoginDialogButtons/styles.module.scss rename to src/components/auth/login/LoginDialogButtons/styles.module.scss diff --git a/src/components/auth/oauth/LoginSocialRegisterButtons/index.tsx b/src/components/auth/oauth/LoginSocialRegisterButtons/index.tsx new file mode 100644 index 00000000..832ab0b4 --- /dev/null +++ b/src/components/auth/oauth/LoginSocialRegisterButtons/index.tsx @@ -0,0 +1,13 @@ +import React, { FC } from 'react'; +import { Button } from '~/components/input/Button'; +import styles from './styles.module.scss'; + +interface IProps {} + +const LoginSocialRegisterButtons: FC = () => ( +
+ +
+); + +export { LoginSocialRegisterButtons }; diff --git a/src/containers/dialogs/LoginSocialRegisterButtons/styles.module.scss b/src/components/auth/oauth/LoginSocialRegisterButtons/styles.module.scss similarity index 100% rename from src/containers/dialogs/LoginSocialRegisterButtons/styles.module.scss rename to src/components/auth/oauth/LoginSocialRegisterButtons/styles.module.scss diff --git a/src/components/auth/restore/RestoreInvalidCode/index.tsx b/src/components/auth/restore/RestoreInvalidCode/index.tsx new file mode 100644 index 00000000..9218116b --- /dev/null +++ b/src/components/auth/restore/RestoreInvalidCode/index.tsx @@ -0,0 +1,27 @@ +import React, { VFC } from 'react'; +import styles from './styles.module.scss'; +import { Group } from '~/components/containers/Group'; +import { Icon } from '~/components/input/Icon'; +import { ERROR_LITERAL, ERRORS } from '~/constants/errors'; +import { Button } from '~/components/input/Button'; + +interface RestoreInvalidCodeProps { + error: string; + onClose: () => void; +} + +const RestoreInvalidCode: VFC = ({ error, onClose }) => ( + + + +
{error || ERROR_LITERAL[ERRORS.CODE_IS_INVALID]}
+ +
+ + + +); + +export { RestoreInvalidCode }; diff --git a/src/components/auth/restore/RestoreInvalidCode/styles.module.scss b/src/components/auth/restore/RestoreInvalidCode/styles.module.scss new file mode 100644 index 00000000..e6f90011 --- /dev/null +++ b/src/components/auth/restore/RestoreInvalidCode/styles.module.scss @@ -0,0 +1,35 @@ +@import "src/styles/variables"; + +.error_shade { + @include outer_shadow(); + + background: $content_bg; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + border-radius: $radius; + padding: $gap * 2; + box-sizing: border-box; + text-transform: uppercase; + font: $font_18_semibold; + text-align: center; + color: $wisegreen; + + svg { + fill: $wisegreen; + } +} + +.error_shade { + color: $red; + + svg { + fill: $red; + } +} diff --git a/src/components/auth/restore/RestoreSent/index.tsx b/src/components/auth/restore/RestoreSent/index.tsx new file mode 100644 index 00000000..0ee86882 --- /dev/null +++ b/src/components/auth/restore/RestoreSent/index.tsx @@ -0,0 +1,25 @@ +import React, { VFC } from 'react'; +import styles from './styles.module.scss'; +import { Icon } from '~/components/input/Icon'; +import { Button } from '~/components/input/Button'; +import { Group } from '~/components/containers/Group'; + +interface RestoreSentProps { + onClose: () => void; +} + +const RestoreSent: VFC = ({ onClose }) => ( + + + +
Проверьте почту, мы отправили на неё код
+ +
+ + + +); + +export { RestoreSent }; diff --git a/src/components/auth/restore/RestoreSent/styles.module.scss b/src/components/auth/restore/RestoreSent/styles.module.scss new file mode 100644 index 00000000..38f949d7 --- /dev/null +++ b/src/components/auth/restore/RestoreSent/styles.module.scss @@ -0,0 +1,27 @@ +@import "src/styles/variables"; + +.shade { + @include outer_shadow(); + + background: $content_bg; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + border-radius: $radius; + padding: $gap * 2; + box-sizing: border-box; + text-transform: uppercase; + font: $font_18_semibold; + text-align: center; + color: $wisegreen; + + svg { + fill: $wisegreen; + } +} diff --git a/src/components/auth/restore/RestoreSuccess/index.tsx b/src/components/auth/restore/RestoreSuccess/index.tsx new file mode 100644 index 00000000..d945d103 --- /dev/null +++ b/src/components/auth/restore/RestoreSuccess/index.tsx @@ -0,0 +1,27 @@ +import React, { VFC } from 'react'; +import { Icon } from '~/components/input/Icon'; +import { Button } from '~/components/input/Button'; +import { Group } from '~/components/containers/Group'; +import styles from './styles.module.scss'; + +interface RestoreSuccessProps { + username?: string; + onClick: () => void; +} + +const RestoreSuccess: VFC = ({ username, onClick }) => ( + + + +
Пароль обновлен
+
Добро пожаловать домой{username ? `, ~${username}` : ''}!
+ +
+ + + +); + +export { RestoreSuccess }; diff --git a/src/components/auth/restore/RestoreSuccess/styles.module.scss b/src/components/auth/restore/RestoreSuccess/styles.module.scss new file mode 100644 index 00000000..38f949d7 --- /dev/null +++ b/src/components/auth/restore/RestoreSuccess/styles.module.scss @@ -0,0 +1,27 @@ +@import "src/styles/variables"; + +.shade { + @include outer_shadow(); + + background: $content_bg; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + border-radius: $radius; + padding: $gap * 2; + box-sizing: border-box; + text-transform: uppercase; + font: $font_18_semibold; + text-align: center; + color: $wisegreen; + + svg { + fill: $wisegreen; + } +} diff --git a/src/components/bars/PlayerBar/index.tsx b/src/components/bars/PlayerBar/index.tsx index b983a150..eda08651 100644 --- a/src/components/bars/PlayerBar/index.tsx +++ b/src/components/bars/PlayerBar/index.tsx @@ -1,10 +1,10 @@ -import React, { useCallback, VFC } from "react"; -import styles from "./styles.module.scss"; -import { Icon } from "~/components/input/Icon"; -import { PlayerState } from "~/constants/player"; -import { path } from "ramda"; -import { IFile } from "~/redux/types"; -import { PlayerProgress } from "~/types/player"; +import React, { useCallback, VFC } from 'react'; +import styles from './styles.module.scss'; +import { Icon } from '~/components/input/Icon'; +import { PlayerState } from '~/constants/player'; +import { path } from 'ramda'; +import { IFile } from '~/types'; +import { PlayerProgress } from '~/types/player'; interface Props { progress: PlayerProgress; diff --git a/src/components/bars/SubmitBar/index.tsx b/src/components/bars/SubmitBar/index.tsx index 4f5829db..edcd28b5 100644 --- a/src/components/bars/SubmitBar/index.tsx +++ b/src/components/bars/SubmitBar/index.tsx @@ -1,26 +1,26 @@ -import React, { FC, useCallback, useState } from "react"; -import { Icon } from "~/components/input/Icon"; -import { Link } from "react-router-dom"; -import classNames from "classnames"; -import { useRouteMatch } from "react-router"; -import styles from "./styles.module.scss"; +import React, { FC, useCallback, useState } from 'react'; +import { Icon } from '~/components/input/Icon'; +import classNames from 'classnames'; +import styles from './styles.module.scss'; +import { useShowModal } from '~/hooks/modal/useShowModal'; +import { Dialog } from '~/constants/modal'; interface Props { isLab?: boolean; } const SubmitBar: FC = ({ isLab }) => { - const { url } = useRouteMatch(); + const showModal = useShowModal(Dialog.CreateNode); const [focused, setFocused] = useState(false); const onFocus = useCallback(() => setFocused(true), [setFocused]); const onBlur = useCallback(() => setFocused(false), [setFocused]); const createUrl = useCallback( - (type: string) => { - return [url.replace(/\/$/, ''), 'create', type].join('/'); + (type: string) => () => { + showModal({ type, isInLab: !!isLab }); }, - [url] + [isLab, showModal] ); const icon = isLab ? 'lab' : 'plus'; @@ -28,21 +28,21 @@ const SubmitBar: FC = ({ isLab }) => { return (
- + - + - + - +
- )} -
-
- ); - } -); - -const Header = connect(mapStateToProps, mapDispatchToProps)(HeaderUnconnected); - -export { Header }; diff --git a/src/components/main/Notifications/index.tsx b/src/components/main/Notifications/index.tsx deleted file mode 100644 index 6f65f41b..00000000 --- a/src/components/main/Notifications/index.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; -import { Icon } from '~/components/input/Icon'; -import styles from './styles.module.scss'; -import { connect } from 'react-redux'; -import { selectAuthUpdates, selectAuthUser } from '~/redux/auth/selectors'; -import { pick } from 'ramda'; -import classNames from 'classnames'; -import * as AUTH_ACTIONS from '~/redux/auth/actions'; -import { NotificationBubble } from '../../notifications/NotificationBubble'; -import { IMessageNotification, INotification } from '~/redux/types'; - -const mapStateToProps = state => ({ - user: pick(['last_seen_messages'], selectAuthUser(state)), - updates: selectAuthUpdates(state), -}); - -const mapDispatchToProps = { - authSetLastSeenMessages: AUTH_ACTIONS.authSetLastSeenMessages, - authOpenProfile: AUTH_ACTIONS.authOpenProfile, -}; - -type IProps = ReturnType & typeof mapDispatchToProps & {}; - -const NotificationsUnconnected: FC = ({ - updates: { last, notifications }, - user: { last_seen_messages }, - authSetLastSeenMessages, - authOpenProfile, -}) => { - const [visible, setVisible] = useState(false); - const has_new = useMemo( - () => - notifications.length && - last && - Date.parse(last) && - (!last_seen_messages || - (Date.parse(last_seen_messages) && Date.parse(last) > Date.parse(last_seen_messages))), - [last, last_seen_messages, notifications] - ); - - const onNotificationClick = useCallback( - (notification: INotification) => { - switch (notification.type) { - case 'message': - if (!(notification as IMessageNotification)?.content?.from?.username) { - return; - } - - return authOpenProfile((notification as IMessageNotification).content.from!.username); - default: - return; - } - }, - [authOpenProfile] - ); - const showList = useCallback(() => setVisible(true), [setVisible]); - const hideList = useCallback(() => setVisible(false), [setVisible]); - - useEffect(() => { - if (!visible || !has_new || !last) return; - authSetLastSeenMessages(last); - }, [visible, last, has_new, authSetLastSeenMessages]); - - return ( -
0, - })} - > -
- {has_new ? : } -
- - {visible && ( - - )} -
- ); -}; - -const Notifications = connect(mapStateToProps, mapDispatchToProps)(NotificationsUnconnected); - -export { Notifications }; diff --git a/src/components/main/Notifications/styles.module.scss b/src/components/main/Notifications/styles.module.scss deleted file mode 100644 index cf110f0a..00000000 --- a/src/components/main/Notifications/styles.module.scss +++ /dev/null @@ -1,51 +0,0 @@ -@import "src/styles/variables"; - -@keyframes ring { - 0% { - transform: rotate(-10deg); - } - - 20% { - transform: rotate(10deg); - } - - 40% { - transform: rotate(-10deg); - } - - 100% { - transform: rotate(0); - } -} - -.wrap { - fill: white; - position: relative; - outline: none; - color: white; - word-wrap: initial; - white-space: initial; - - &.active { - .icon { - opacity: 1; - } - } - - &.is_new { - .icon { - animation: ring 1s infinite alternate; - opacity: 1; - - svg { - fill: $red; - } - } - } -} - -.icon { - outline: none; - cursor: pointer; - opacity: 0.5; -} diff --git a/src/components/main/SidePane/index.tsx b/src/components/main/SidePane/index.tsx index 2db2bfb7..e952bc87 100644 --- a/src/components/main/SidePane/index.tsx +++ b/src/components/main/SidePane/index.tsx @@ -1,7 +1,7 @@ -import React, { FC, useCallback, useEffect, useState } from "react"; -import classNames from "classnames"; -import styles from "./styles.module.scss"; -import { Group } from "~/components/containers/Group"; +import React, { FC, useCallback, useEffect, useState } from 'react'; +import classNames from 'classnames'; +import styles from './styles.module.scss'; +import { Group } from '~/components/containers/Group'; interface IProps {} diff --git a/src/components/main/UserButton/index.tsx b/src/components/main/UserButton/index.tsx index b4e31d51..df563163 100644 --- a/src/components/main/UserButton/index.tsx +++ b/src/components/main/UserButton/index.tsx @@ -1,28 +1,25 @@ -import React, { FC, useCallback } from "react"; -import { Group } from "~/components/containers/Group"; -import styles from "./styles.module.scss"; -import { getURL } from "~/utils/dom"; -import { Icon } from "~/components/input/Icon"; -import { IUser } from "~/redux/auth/types"; -import { PRESETS } from "~/constants/urls"; -import { authOpenProfile } from "~/redux/auth/actions"; +import React, { FC, useCallback } from 'react'; +import { Group } from '~/components/containers/Group'; +import styles from './styles.module.scss'; +import { getURL } from '~/utils/dom'; +import { Icon } from '~/components/input/Icon'; +import { IUser } from '~/types/auth'; +import { PRESETS } from '~/constants/urls'; interface IProps { user: Partial; onLogout: () => void; - authOpenProfile: typeof authOpenProfile; + authOpenProfile: () => void; } const UserButton: FC = ({ user: { username, photo }, authOpenProfile, onLogout }) => { const onProfileOpen = useCallback(() => { - if (!username) return; - authOpenProfile(username); - }, [authOpenProfile, username]); + authOpenProfile(); + }, [authOpenProfile]); const onSettingsOpen = useCallback(() => { - if (!username) return; - authOpenProfile(username); - }, [authOpenProfile, username]); + authOpenProfile(); + }, [authOpenProfile]); return (
diff --git a/src/components/media/AudioPlayer/index.tsx b/src/components/media/AudioPlayer/index.tsx index a68e8b65..635c3c68 100644 --- a/src/components/media/AudioPlayer/index.tsx +++ b/src/components/media/AudioPlayer/index.tsx @@ -1,11 +1,11 @@ -import React, { memo, useCallback, useMemo } from "react"; -import { IFile } from "~/redux/types"; -import classNames from "classnames"; -import styles from "./styles.module.scss"; -import { Icon } from "~/components/input/Icon"; -import { InputText } from "~/components/input/InputText"; -import { PlayerState } from "~/constants/player"; -import { useAudioPlayer } from "~/utils/providers/AudioPlayerProvider"; +import React, { memo, useCallback, useMemo } from 'react'; +import { IFile } from '~/types'; +import classNames from 'classnames'; +import styles from './styles.module.scss'; +import { Icon } from '~/components/input/Icon'; +import { InputText } from '~/components/input/InputText'; +import { PlayerState } from '~/constants/player'; +import { useAudioPlayer } from '~/utils/providers/AudioPlayerProvider'; type Props = { file: IFile; diff --git a/src/components/media/ImagePreloader/index.tsx b/src/components/media/ImagePreloader/index.tsx index 597d63dd..654f9989 100644 --- a/src/components/media/ImagePreloader/index.tsx +++ b/src/components/media/ImagePreloader/index.tsx @@ -1,13 +1,13 @@ -import React, { FC, MouseEventHandler, useCallback, useMemo, useState } from "react"; -import classNames from "classnames"; -import { getURL } from "~/utils/dom"; -import { PRESETS } from "~/constants/urls"; -import styles from "./styles.module.scss"; -import { IFile } from "~/redux/types"; -import { LoaderCircle } from "~/components/input/LoaderCircle"; -import { Icon } from "~/components/input/Icon"; -import { useResizeHandler } from "~/hooks/dom/useResizeHandler"; -import { DEFAULT_DOMINANT_COLOR } from "~/constants/node"; +import React, { FC, MouseEventHandler, useCallback, useMemo, useState } from 'react'; +import classNames from 'classnames'; +import { getURL } from '~/utils/dom'; +import { PRESETS } from '~/constants/urls'; +import styles from './styles.module.scss'; +import { IFile } from '~/types'; +import { LoaderCircle } from '~/components/input/LoaderCircle'; +import { Icon } from '~/components/input/Icon'; +import { useResizeHandler } from '~/hooks/dom/useResizeHandler'; +import { DEFAULT_DOMINANT_COLOR } from '~/constants/node'; interface IProps { file: IFile; diff --git a/src/components/media/ImagePreloader/styles.module.scss b/src/components/media/ImagePreloader/styles.module.scss index 388806cd..98a92a1f 100644 --- a/src/components/media/ImagePreloader/styles.module.scss +++ b/src/components/media/ImagePreloader/styles.module.scss @@ -1,4 +1,4 @@ -@import "~/styles/variables.scss"; +@import "src/styles/variables.scss"; .image { position: absolute; diff --git a/src/components/node/CommendDeleted/index.tsx b/src/components/node/CommendDeleted/index.tsx index 70b4f561..d4d8274e 100644 --- a/src/components/node/CommendDeleted/index.tsx +++ b/src/components/node/CommendDeleted/index.tsx @@ -1,7 +1,7 @@ -import React, { FC, useCallback } from "react"; -import styles from "./styles.module.scss"; -import { Button } from "~/components/input/Button"; -import { IComment } from "~/redux/types"; +import React, { FC, useCallback } from 'react'; +import styles from './styles.module.scss'; +import { Button } from '~/components/input/Button'; +import { IComment } from '~/types'; interface IProps { id: IComment['id']; diff --git a/src/components/node/MenuButton/index.tsx b/src/components/node/MenuButton/index.tsx index c4a24b8b..509a918d 100644 --- a/src/components/node/MenuButton/index.tsx +++ b/src/components/node/MenuButton/index.tsx @@ -1,7 +1,7 @@ -import React, { FC } from "react"; -import styles from "./styles.module.scss"; -import { Group } from "~/components/containers/Group"; -import { Filler } from "~/components/containers/Filler"; +import React, { FC } from 'react'; +import styles from './styles.module.scss'; +import { Group } from '~/components/containers/Group'; +import { Filler } from '~/components/containers/Filler'; interface IProps { title: string; diff --git a/src/components/node/NodeAudioBlock/index.tsx b/src/components/node/NodeAudioBlock/index.tsx index 4766a24b..1da925ed 100644 --- a/src/components/node/NodeAudioBlock/index.tsx +++ b/src/components/node/NodeAudioBlock/index.tsx @@ -1,8 +1,8 @@ -import React, { FC } from "react"; -import { AudioPlayer } from "~/components/media/AudioPlayer"; -import styles from "./styles.module.scss"; -import { INodeComponentProps } from "~/constants/node"; -import { useNodeAudios } from "~/hooks/node/useNodeAudios"; +import React, { FC } from 'react'; +import { AudioPlayer } from '~/components/media/AudioPlayer'; +import styles from './styles.module.scss'; +import { INodeComponentProps } from '~/constants/node'; +import { useNodeAudios } from '~/hooks/node/useNodeAudios'; interface IProps extends INodeComponentProps {} diff --git a/src/components/node/NodeAudioImageBlock/index.tsx b/src/components/node/NodeAudioImageBlock/index.tsx index 4e355c5e..ae430806 100644 --- a/src/components/node/NodeAudioImageBlock/index.tsx +++ b/src/components/node/NodeAudioImageBlock/index.tsx @@ -1,10 +1,10 @@ -import React, { FC } from "react"; -import styles from "./styles.module.scss"; -import { path } from "ramda"; -import { getURL } from "~/utils/dom"; -import { PRESETS } from "~/constants/urls"; -import { INodeComponentProps } from "~/constants/node"; -import { useNodeImages } from "~/hooks/node/useNodeImages"; +import React, { FC } from 'react'; +import styles from './styles.module.scss'; +import { path } from 'ramda'; +import { getURL } from '~/utils/dom'; +import { PRESETS } from '~/constants/urls'; +import { INodeComponentProps } from '~/constants/node'; +import { useNodeImages } from '~/hooks/node/useNodeImages'; interface IProps extends INodeComponentProps {} diff --git a/src/components/node/NodeAuthorBlock/index.tsx b/src/components/node/NodeAuthorBlock/index.tsx index ca74ce3f..045b2659 100644 --- a/src/components/node/NodeAuthorBlock/index.tsx +++ b/src/components/node/NodeAuthorBlock/index.tsx @@ -1,9 +1,9 @@ -import React, { FC, useCallback } from "react"; -import styles from "./styles.module.scss"; -import { Avatar } from "~/components/common/Avatar"; -import { openUserProfile } from "~/utils/user"; -import { useUserDescription } from "~/hooks/user/useUserDescription"; -import { INodeUser } from "~/redux/types"; +import React, { FC, useCallback } from 'react'; +import styles from './styles.module.scss'; +import { Avatar } from '~/components/common/Avatar'; +import { openUserProfile } from '~/utils/user'; +import { useUserDescription } from '~/hooks/auth/useUserDescription'; +import { INodeUser } from '~/types'; interface Props { user?: INodeUser; diff --git a/src/components/node/NodeAuthorBlock/styles.module.scss b/src/components/node/NodeAuthorBlock/styles.module.scss index 0d400ed7..6a77ee84 100644 --- a/src/components/node/NodeAuthorBlock/styles.module.scss +++ b/src/components/node/NodeAuthorBlock/styles.module.scss @@ -1,4 +1,4 @@ -@import "~/styles/variables.scss"; +@import "src/styles/variables.scss"; div.block { @include inner_shadow_active; diff --git a/src/components/node/NodeCommentForm/index.tsx b/src/components/node/NodeCommentForm/index.tsx index b07a08f4..a4e72b52 100644 --- a/src/components/node/NodeCommentForm/index.tsx +++ b/src/components/node/NodeCommentForm/index.tsx @@ -1,8 +1,8 @@ -import React, { FC } from "react"; -import { CommentWrapper } from "~/components/containers/CommentWrapper"; -import { CommentForm } from "~/components/comment/CommentForm"; -import { IComment } from "~/redux/types"; -import { IUser } from "~/redux/auth/types"; +import React, { FC } from 'react'; +import { CommentWrapper } from '~/components/containers/CommentWrapper'; +import { CommentForm } from '~/components/comment/CommentForm'; +import { IComment } from '~/types'; +import { IUser } from '~/types/auth'; interface NodeCommentFormProps { user: IUser; diff --git a/src/components/node/NodeDeletedBadge/index.tsx b/src/components/node/NodeDeletedBadge/index.tsx index 401d58e5..2c87f773 100644 --- a/src/components/node/NodeDeletedBadge/index.tsx +++ b/src/components/node/NodeDeletedBadge/index.tsx @@ -1,5 +1,5 @@ -import React, { FC } from "react"; -import styles from "./styles.module.scss"; +import React, { FC } from 'react'; +import styles from './styles.module.scss'; interface IProps {} diff --git a/src/components/node/NodeImageSwiperBlock/styles.module.scss b/src/components/node/NodeImageSwiperBlock/styles.module.scss index f587c8ef..b418ccf4 100644 --- a/src/components/node/NodeImageSwiperBlock/styles.module.scss +++ b/src/components/node/NodeImageSwiperBlock/styles.module.scss @@ -1,4 +1,4 @@ -@import "~/styles/variables.scss"; +@import "src/styles/variables.scss"; .wrapper { border-radius: $radius; diff --git a/src/components/node/NodeNoComments/index.tsx b/src/components/node/NodeNoComments/index.tsx index 54f6a15e..149a01f6 100644 --- a/src/components/node/NodeNoComments/index.tsx +++ b/src/components/node/NodeNoComments/index.tsx @@ -1,9 +1,9 @@ -import React, { FC, useMemo } from "react"; -import styles from "./styles.module.scss"; -import { Group } from "~/components/containers/Group"; -import classNames from "classnames"; -import { ERRORS } from "~/constants/errors"; -import { t } from "~/utils/trans"; +import React, { FC, useMemo } from 'react'; +import styles from './styles.module.scss'; +import { Group } from '~/components/containers/Group'; +import classNames from 'classnames'; +import { ERRORS } from '~/constants/errors'; +import { t } from '~/utils/trans'; interface IProps { is_loading?: boolean; diff --git a/src/components/node/NodeRelated/index.tsx b/src/components/node/NodeRelated/index.tsx index fde745c7..13d4f8b2 100644 --- a/src/components/node/NodeRelated/index.tsx +++ b/src/components/node/NodeRelated/index.tsx @@ -1,9 +1,9 @@ -import React, { FC, ReactElement } from "react"; -import styles from "./styles.module.scss"; -import { Group } from "~/components/containers/Group"; -import { INode } from "~/redux/types"; -import { NodeRelatedItem } from "~/components/node/NodeRelatedItem"; -import { SubTitle } from "~/components/common/SubTitle"; +import React, { FC, ReactElement } from 'react'; +import styles from './styles.module.scss'; +import { Group } from '~/components/containers/Group'; +import { INode } from '~/types'; +import { NodeRelatedItem } from '~/components/node/NodeRelatedItem'; +import { SubTitle } from '~/components/common/SubTitle'; interface IProps { title: ReactElement | string; diff --git a/src/components/node/NodeRelated/placeholder.tsx b/src/components/node/NodeRelated/placeholder.tsx index 8e4b020c..4019e92c 100644 --- a/src/components/node/NodeRelated/placeholder.tsx +++ b/src/components/node/NodeRelated/placeholder.tsx @@ -1,10 +1,10 @@ -import React, { FC, memo } from "react"; -import styles from "./styles.module.scss"; -import cell_style from "~/components/node/NodeRelatedItem/styles.module.scss"; -import { Group } from "~/components/containers/Group"; -import { Placeholder } from "~/components/placeholders/Placeholder"; -import range from "ramda/es/range"; -import classNames from "classnames"; +import React, { FC, memo } from 'react'; +import styles from './styles.module.scss'; +import cell_style from '~/components/node/NodeRelatedItem/styles.module.scss'; +import { Group } from '~/components/containers/Group'; +import { Placeholder } from '~/components/placeholders/Placeholder'; +import range from 'ramda/es/range'; +import classNames from 'classnames'; interface IProps {} diff --git a/src/components/node/NodeRelatedBlock/index.tsx b/src/components/node/NodeRelatedBlock/index.tsx index 8a0d6ccd..c377e975 100644 --- a/src/components/node/NodeRelatedBlock/index.tsx +++ b/src/components/node/NodeRelatedBlock/index.tsx @@ -1,10 +1,10 @@ -import React, { FC } from "react"; -import { NodeRelatedPlaceholder } from "~/components/node/NodeRelated/placeholder"; -import { NodeRelated } from "~/components/node/NodeRelated"; -import { URLS } from "~/constants/urls"; -import { INode } from "~/redux/types"; -import { INodeRelated } from "~/types/node"; -import { Link } from "react-router-dom"; +import React, { FC } from 'react'; +import { NodeRelatedPlaceholder } from '~/components/node/NodeRelated/placeholder'; +import { NodeRelated } from '~/components/node/NodeRelated'; +import { URLS } from '~/constants/urls'; +import { INode } from '~/types'; +import { INodeRelated } from '~/types/node'; +import { Link } from 'react-router-dom'; interface IProps { isLoading: boolean; diff --git a/src/components/node/NodeRelatedItem/index.tsx b/src/components/node/NodeRelatedItem/index.tsx index 619da4eb..ddea53c3 100644 --- a/src/components/node/NodeRelatedItem/index.tsx +++ b/src/components/node/NodeRelatedItem/index.tsx @@ -1,12 +1,12 @@ -import React, { FC, memo, useCallback, useEffect, useMemo, useRef, useState } from "react"; -import styles from "./styles.module.scss"; -import classNames from "classnames"; -import { INode } from "~/redux/types"; -import { PRESETS, URLS } from "~/constants/urls"; -import { RouteComponentProps, withRouter } from "react-router"; -import { getURL } from "~/utils/dom"; -import { Avatar } from "~/components/common/Avatar"; -import { useColorGradientFromString } from "~/hooks/color/useColorGradientFromString"; +import React, { FC, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import styles from './styles.module.scss'; +import classNames from 'classnames'; +import { INode } from '~/types'; +import { PRESETS, URLS } from '~/constants/urls'; +import { RouteComponentProps, withRouter } from 'react-router'; +import { getURL } from '~/utils/dom'; +import { Avatar } from '~/components/common/Avatar'; +import { useColorGradientFromString } from '~/hooks/color/useColorGradientFromString'; type IProps = RouteComponentProps & { item: Partial; diff --git a/src/components/node/NodeTags/index.tsx b/src/components/node/NodeTags/index.tsx index 58fdff36..f499d7aa 100644 --- a/src/components/node/NodeTags/index.tsx +++ b/src/components/node/NodeTags/index.tsx @@ -1,6 +1,6 @@ -import React, { FC, memo } from "react"; -import { ITag } from "~/redux/types"; -import { Tags } from "~/containers/tags/Tags"; +import React, { FC, memo } from 'react'; +import { ITag } from '~/types'; +import { Tags } from '~/containers/tags/Tags'; interface IProps { is_deletable?: boolean; diff --git a/src/components/node/NodeTagsBlock/index.tsx b/src/components/node/NodeTagsBlock/index.tsx index 88f5138f..3cd17fec 100644 --- a/src/components/node/NodeTagsBlock/index.tsx +++ b/src/components/node/NodeTagsBlock/index.tsx @@ -1,6 +1,6 @@ -import React, { FC } from "react"; -import { NodeTags } from "~/components/node/NodeTags"; -import { useTagContext } from "~/utils/context/TagsContextProvider"; +import React, { FC } from 'react'; +import { NodeTags } from '~/components/node/NodeTags'; +import { useTagContext } from '~/utils/context/TagsContextProvider'; interface IProps {} diff --git a/src/components/node/NodeTagsPlaceholder/index.tsx b/src/components/node/NodeTagsPlaceholder/index.tsx index 8332ac8b..bdcc2fa3 100644 --- a/src/components/node/NodeTagsPlaceholder/index.tsx +++ b/src/components/node/NodeTagsPlaceholder/index.tsx @@ -1,6 +1,6 @@ -import React, { FC, memo } from "react"; -import { ITag } from "~/redux/types"; -import { Tags } from "~/containers/tags/Tags"; +import React, { FC, memo } from 'react'; +import { ITag } from '~/types'; +import { Tags } from '~/containers/tags/Tags'; interface IProps { is_editable?: boolean; diff --git a/src/components/node/NodeTextBlock/index.tsx b/src/components/node/NodeTextBlock/index.tsx index 3ab865c6..16ecb9c0 100644 --- a/src/components/node/NodeTextBlock/index.tsx +++ b/src/components/node/NodeTextBlock/index.tsx @@ -1,10 +1,10 @@ -import React, { FC, useMemo } from "react"; -import { path } from "ramda"; -import { formatTextParagraphs } from "~/utils/dom"; -import { INodeComponentProps } from "~/constants/node"; -import classNames from "classnames"; -import styles from "./styles.module.scss"; -import markdown from "~/styles/common/markdown.module.scss"; +import React, { FC, useMemo } from 'react'; +import { path } from 'ramda'; +import { formatTextParagraphs } from '~/utils/dom'; +import { INodeComponentProps } from '~/constants/node'; +import classNames from 'classnames'; +import styles from './styles.module.scss'; +import markdown from '~/styles/common/markdown.module.scss'; interface IProps extends INodeComponentProps {} diff --git a/src/components/node/NodeTitle/index.tsx b/src/components/node/NodeTitle/index.tsx index 0df4597e..8fc1c26b 100644 --- a/src/components/node/NodeTitle/index.tsx +++ b/src/components/node/NodeTitle/index.tsx @@ -1,11 +1,9 @@ -import React, { memo, VFC } from "react"; -import styles from "./styles.module.scss"; -import { Icon } from "~/components/input/Icon"; -import classNames from "classnames"; -import { Placeholder } from "~/components/placeholders/Placeholder"; -import { getPrettyDate } from "~/utils/dom"; -import { URLS } from "~/constants/urls"; -import { Link } from "react-router-dom"; +import React, { memo, VFC } from 'react'; +import styles from './styles.module.scss'; +import { Icon } from '~/components/input/Icon'; +import classNames from 'classnames'; +import { Placeholder } from '~/components/placeholders/Placeholder'; +import { getPrettyDate } from '~/utils/dom'; interface IProps { id?: number; @@ -27,6 +25,7 @@ interface IProps { onLike: () => void; onStar: () => void; onLock: () => void; + onEdit: () => void; } const NodeTitle: VFC = memo( @@ -50,6 +49,7 @@ const NodeTitle: VFC = memo( onStar, onLike, onLock, + onEdit, }) => { return (
@@ -91,11 +91,7 @@ const NodeTitle: VFC = memo(
- {!!id && ( - - - - )} + {!!id && }
)} diff --git a/src/components/node/NodeTitle/styles.module.scss b/src/components/node/NodeTitle/styles.module.scss index 45ee79cf..5645c83a 100644 --- a/src/components/node/NodeTitle/styles.module.scss +++ b/src/components/node/NodeTitle/styles.module.scss @@ -198,7 +198,7 @@ position: relative; flex: 0 0 32px; - .is_liked { + &.is_liked { svg { fill: $red; } diff --git a/src/components/node/NodeVideoBlock/index.tsx b/src/components/node/NodeVideoBlock/index.tsx index 7625f489..7bcda3eb 100644 --- a/src/components/node/NodeVideoBlock/index.tsx +++ b/src/components/node/NodeVideoBlock/index.tsx @@ -1,7 +1,7 @@ -import React, { FC, useMemo } from "react"; -import styles from "./styles.module.scss"; -import { path } from "ramda"; -import { INodeComponentProps } from "~/constants/node"; +import React, { FC, useMemo } from 'react'; +import styles from './styles.module.scss'; +import { path } from 'ramda'; +import { INodeComponentProps } from '~/constants/node'; interface IProps extends INodeComponentProps {} diff --git a/src/components/notifications/NotificationBubble/index.tsx b/src/components/notifications/NotificationBubble/index.tsx index 58324f85..091641e0 100644 --- a/src/components/notifications/NotificationBubble/index.tsx +++ b/src/components/notifications/NotificationBubble/index.tsx @@ -1,9 +1,9 @@ -import React, { createElement, FC } from "react"; -import { INotification, NOTIFICATION_TYPES } from "~/redux/types"; -import styles from "./styles.module.scss"; -import { NotificationMessage } from "../NotificationMessage"; -import { Icon } from "~/components/input/Icon"; -import { useRandomPhrase } from "~/constants/phrases"; +import React, { createElement, FC } from 'react'; +import { INotification, NOTIFICATION_TYPES } from '~/types'; +import styles from './styles.module.scss'; +import { NotificationMessage } from '../NotificationMessage'; +import { Icon } from '~/components/input/Icon'; +import { useRandomPhrase } from '~/constants/phrases'; interface IProps { notifications: INotification[]; diff --git a/src/components/notifications/NotificationMessage/index.tsx b/src/components/notifications/NotificationMessage/index.tsx index 8819ae64..fa6523c1 100644 --- a/src/components/notifications/NotificationMessage/index.tsx +++ b/src/components/notifications/NotificationMessage/index.tsx @@ -1,7 +1,7 @@ -import React, { FC, useCallback } from "react"; -import styles from "~/components/notifications/NotificationBubble/styles.module.scss"; -import { Icon } from "~/components/input/Icon"; -import { IMessageNotification, INotification } from "~/redux/types"; +import React, { FC, useCallback } from 'react'; +import styles from '~/components/notifications/NotificationBubble/styles.module.scss'; +import { Icon } from '~/components/input/Icon'; +import { IMessageNotification, INotification } from '~/types'; interface IProps { notification: IMessageNotification; diff --git a/src/components/placeholders/Paragraph/index.tsx b/src/components/placeholders/Paragraph/index.tsx index fcf6c665..7d9b411a 100644 --- a/src/components/placeholders/Paragraph/index.tsx +++ b/src/components/placeholders/Paragraph/index.tsx @@ -1,7 +1,7 @@ -import React, { FC, useMemo } from "react"; -import { Placeholder, PlaceholderProps } from "~/components/placeholders/Placeholder"; -import styles from "./styles.module.scss"; -import { Group } from "~/components/containers/Group"; +import React, { FC, useMemo } from 'react'; +import { Placeholder, PlaceholderProps } from '~/components/placeholders/Placeholder'; +import styles from './styles.module.scss'; +import { Group } from '~/components/containers/Group'; type Props = PlaceholderProps & { lines?: number; diff --git a/src/components/profile/Message/index.tsx b/src/components/profile/Message/index.tsx index 618bcfa9..0c5bdcce 100644 --- a/src/components/profile/Message/index.tsx +++ b/src/components/profile/Message/index.tsx @@ -1,11 +1,11 @@ -import React, { FC } from "react"; -import { IMessage } from "~/redux/types"; -import styles from "./styles.module.scss"; -import { formatText, getPrettyDate, getURL } from "~/utils/dom"; -import { PRESETS } from "~/constants/urls"; -import classNames from "classnames"; -import { Group } from "~/components/containers/Group"; -import markdown from "~/styles/common/markdown.module.scss"; +import React, { FC } from 'react'; +import { IMessage } from '~/types'; +import styles from './styles.module.scss'; +import { formatText, getPrettyDate, getURL } from '~/utils/dom'; +import { PRESETS } from '~/constants/urls'; +import classNames from 'classnames'; +import { Group } from '~/components/containers/Group'; +import markdown from '~/styles/common/markdown.module.scss'; interface IProps { message: IMessage; diff --git a/src/components/profile/ProfileAccounts/index.tsx b/src/components/profile/ProfileAccounts/index.tsx deleted file mode 100644 index 01c820f5..00000000 --- a/src/components/profile/ProfileAccounts/index.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import React, { FC, Fragment, useCallback, useEffect } from 'react'; -import { ISocialProvider } from '~/redux/auth/types'; -import styles from './styles.module.scss'; -import { Placeholder } from '~/components/placeholders/Placeholder'; -import { Icon } from '~/components/input/Icon'; -import { Button } from '~/components/input/Button'; -import { Group } from '~/components/containers/Group'; -import * as AUTH_ACTIONS from '~/redux/auth/actions'; -import { selectAuthProfile } from '~/redux/auth/selectors'; -import { IState } from '~/redux/store'; -import { connect } from 'react-redux'; -import { API } from '~/constants/api'; -import { ProfileAccountsError } from '~/components/profile/ProfileAccountsError'; - -const mapStateToProps = (state: IState) => selectAuthProfile(state).socials; -const mapDispatchToProps = { - authGetSocials: AUTH_ACTIONS.authGetSocials, - authDropSocial: AUTH_ACTIONS.authDropSocial, - authAttachSocial: AUTH_ACTIONS.authAttachSocial, - authSetSocials: AUTH_ACTIONS.authSetSocials, -}; - -type IProps = ReturnType & typeof mapDispatchToProps & {}; - -const SOCIAL_ICONS: Record = { - vkontakte: 'vk', - google: 'google', -}; - -const ProfileAccountsUnconnected: FC = ({ - authGetSocials, - authDropSocial, - authAttachSocial, - authSetSocials, - accounts, - is_loading, - error, -}) => { - const onMessage = useCallback( - (event: MessageEvent) => { - if (!event?.data?.type) return; - - switch (event?.data?.type) { - case 'oauth_processed': - return authAttachSocial(event?.data?.payload?.token); - case 'oauth_error': - return authSetSocials({ error: event?.data?.payload?.error || '' }); - default: - return; - } - }, - [authAttachSocial, authSetSocials] - ); - - const openOauthWindow = useCallback( - (provider: ISocialProvider) => () => { - window.open(API.USER.OAUTH_WINDOW(provider), '', 'width=600,height=400'); - }, - [] - ); - - const resetErrors = useCallback(() => authSetSocials({ error: '' }), [authSetSocials]); - - useEffect(() => { - authGetSocials(); - }, [authGetSocials]); - - useEffect(() => { - window.addEventListener('message', onMessage); - return () => window.removeEventListener('message', onMessage); - }, [onMessage]); - - return ( - - {error && } - - -

- Ты можешь входить в Убежище, используя аккаунты на других сайтах вместо ввода логина и - пароля. -

- -

- Мы честно украдём и будем хранить твои имя, фото и адрес на этом сайте, но никому о них не - расскажем. -

-
- - {is_loading && ( -
- {[...new Array(accounts.length || 1)].map((_, i) => ( - - - - - ))} -
- )} - - {!is_loading && accounts.length > 0 && ( -
- {!is_loading && - accounts.map(it => ( -
-
-
- -
-
- -
{it.name || it.id}
- -
- authDropSocial(it.provider, it.id)} /> -
-
- ))} -
- )} - - - - - - -
- ); -}; - -const ProfileAccounts = connect(mapStateToProps, mapDispatchToProps)(ProfileAccountsUnconnected); - -export { ProfileAccounts }; diff --git a/src/components/profile/ProfileAccountsError/index.tsx b/src/components/profile/ProfileAccountsError/index.tsx index 3dbe5bde..ad65fe5b 100644 --- a/src/components/profile/ProfileAccountsError/index.tsx +++ b/src/components/profile/ProfileAccountsError/index.tsx @@ -1,8 +1,8 @@ -import React, { FC } from "react"; -import styles from "./styles.module.scss"; -import { Group } from "~/components/containers/Group"; -import { ERROR_LITERAL } from "~/constants/errors"; -import { Button } from "~/components/input/Button"; +import React, { FC } from 'react'; +import styles from './styles.module.scss'; +import { Group } from '~/components/containers/Group'; +import { ERROR_LITERAL } from '~/constants/errors'; +import { Button } from '~/components/input/Button'; interface IProps { onClose: () => void; diff --git a/src/components/profile/ProfileAvatar/index.tsx b/src/components/profile/ProfileAvatar/index.tsx index b5a3ed79..e1723efe 100644 --- a/src/components/profile/ProfileAvatar/index.tsx +++ b/src/components/profile/ProfileAvatar/index.tsx @@ -3,7 +3,7 @@ import styles from './styles.module.scss'; import { getURL } from '~/utils/dom'; import { PRESETS } from '~/constants/urls'; import { Icon } from '~/components/input/Icon'; -import { IFile } from '~/redux/types'; +import { IFile } from '~/types'; export interface ProfileAvatarProps { canEdit: boolean; diff --git a/src/components/profile/ProfileDescription/index.tsx b/src/components/profile/ProfileDescription/index.tsx index 683ccadb..fbf2ec28 100644 --- a/src/components/profile/ProfileDescription/index.tsx +++ b/src/components/profile/ProfileDescription/index.tsx @@ -6,24 +6,29 @@ import { Group } from '~/components/containers/Group'; import markdown from '~/styles/common/markdown.module.scss'; import classNames from 'classnames'; import { useProfileContext } from '~/utils/providers/ProfileProvider'; +import { useUser } from '~/hooks/auth/useUser'; const ProfileDescription: FC = () => { const { profile, isLoading } = useProfileContext(); + const { user } = useUser(); + + const isOwn = user?.id === profile?.id; + const description = isOwn ? user.description : profile.description; + const fullName = isOwn ? user.fullname : profile.fullname; + const username = isOwn ? user.username : profile.username; if (isLoading) return ; return (
- {!!profile?.description && ( + {!!description ? ( - )} - - {!profile?.description && ( + ) : (
- {profile?.fullname || profile?.username} пока ничего не рассказал о себе + {fullName || username} пока ничего не рассказал о себе
)}
diff --git a/src/components/profile/ProfileDescription/styles.module.scss b/src/components/profile/ProfileDescription/styles.module.scss index 3c1a63d0..0095bad7 100644 --- a/src/components/profile/ProfileDescription/styles.module.scss +++ b/src/components/profile/ProfileDescription/styles.module.scss @@ -6,6 +6,8 @@ display: flex; box-sizing: border-box; flex-direction: column; + align-items: center; + justify-content: center; } .placeholder { diff --git a/src/components/profile/ProfileSettings/index.tsx b/src/components/profile/ProfileSettings/index.tsx index 8ca11c68..74ff3227 100644 --- a/src/components/profile/ProfileSettings/index.tsx +++ b/src/components/profile/ProfileSettings/index.tsx @@ -6,22 +6,22 @@ import { Group } from '~/components/containers/Group'; import { Filler } from '~/components/containers/Filler'; import { InputText } from '~/components/input/InputText'; import { ERROR_LITERAL } from '~/constants/errors'; -import { ProfileAccounts } from '~/components/profile/ProfileAccounts'; +import { ProfileAccounts } from '~/containers/profile/ProfileAccounts'; import classNames from 'classnames'; -import { useUser } from '~/hooks/user/userUser'; -import { useProfileContext } from '~/utils/providers/ProfileProvider'; +import { useUser } from '~/hooks/auth/useUser'; import { useProfileForm } from '~/hooks/profile/useProfileForm'; import { has } from 'ramda'; +import { usePatchUser } from '~/hooks/auth/usePatchUser'; const getError = (error?: string) => (error && has(error, ERROR_LITERAL) ? error : undefined); const ProfileSettings: FC = () => { - const user = useUser(); - const { updateProfile } = useProfileContext(); + const { user } = useUser(); + const { save } = usePatchUser(); const { handleSubmit, values, errors, handleChange } = useProfileForm( { ...user, password: '', newPassword: '' }, - updateProfile + save ); return ( diff --git a/src/components/profile/ProfileSidebarMenu/index.tsx b/src/components/profile/ProfileSidebarMenu/index.tsx index 344a8d83..dafbae33 100644 --- a/src/components/profile/ProfileSidebarMenu/index.tsx +++ b/src/components/profile/ProfileSidebarMenu/index.tsx @@ -1,7 +1,7 @@ -import React, { FC } from "react"; -import styles from "./styles.module.scss"; -import { Icon } from "~/components/input/Icon"; -import { Link } from "react-router-dom"; +import React, { FC } from 'react'; +import styles from './styles.module.scss'; +import { Icon } from '~/components/input/Icon'; +import { Link } from 'react-router-dom'; interface IProps { path: string; diff --git a/src/components/profile/ProfileSidebarSettings/index.tsx b/src/components/profile/ProfileSidebarSettings/index.tsx index beb1f4f3..8e30fc7d 100644 --- a/src/components/profile/ProfileSidebarSettings/index.tsx +++ b/src/components/profile/ProfileSidebarSettings/index.tsx @@ -1,8 +1,8 @@ -import React, { FC } from "react"; -import { ProfileSettings } from "~/components/profile/ProfileSettings"; -import styles from "./styles.module.scss"; -import { Filler } from "~/components/containers/Filler"; -import { Button } from "~/components/input/Button"; +import React, { FC } from 'react'; +import { ProfileSettings } from '~/components/profile/ProfileSettings'; +import styles from './styles.module.scss'; +import { Filler } from '~/components/containers/Filler'; +import { Button } from '~/components/input/Button'; interface IProps {} diff --git a/src/components/sidebar/TagSidebarList/index.tsx b/src/components/sidebar/TagSidebarList/index.tsx index 7b1ef1ed..1f083981 100644 --- a/src/components/sidebar/TagSidebarList/index.tsx +++ b/src/components/sidebar/TagSidebarList/index.tsx @@ -1,7 +1,7 @@ -import React, { FC } from "react"; -import { INode } from "~/redux/types"; -import styles from "./styles.module.scss"; -import { FlowRecentItem } from "~/components/flow/FlowRecentItem"; +import React, { FC } from 'react'; +import { INode } from '~/types'; +import styles from './styles.module.scss'; +import { FlowRecentItem } from '~/components/flow/FlowRecentItem'; interface IProps { nodes: INode[]; diff --git a/src/components/tags/Tag/index.tsx b/src/components/tags/Tag/index.tsx index 14074d6c..509a786e 100644 --- a/src/components/tags/Tag/index.tsx +++ b/src/components/tags/Tag/index.tsx @@ -1,5 +1,5 @@ import React, { FC, FocusEventHandler, useCallback } from 'react'; -import { ITag } from '~/redux/types'; +import { ITag } from '~/types'; import { TagWrapper } from '~/components/tags/TagWrapper'; const getTagFeature = (tag: Partial) => { diff --git a/src/components/tags/TagAutocomplete/index.tsx b/src/components/tags/TagAutocomplete/index.tsx index dd43f885..3949c267 100644 --- a/src/components/tags/TagAutocomplete/index.tsx +++ b/src/components/tags/TagAutocomplete/index.tsx @@ -1,9 +1,9 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState, VFC } from "react"; -import styles from "./styles.module.scss"; -import classNames from "classnames"; -import { separateTagOptions } from "~/utils/tag"; -import { TagAutocompleteRow } from "~/components/tags/TagAutocompleteRow"; -import { usePopper } from "react-popper"; +import React, { useCallback, useEffect, useMemo, useRef, useState, VFC } from 'react'; +import styles from './styles.module.scss'; +import classNames from 'classnames'; +import { separateTagOptions } from '~/utils/tag'; +import { TagAutocompleteRow } from '~/components/tags/TagAutocompleteRow'; +import { usePopper } from 'react-popper'; interface TagAutocompleteProps { exclude: string[]; @@ -11,6 +11,7 @@ interface TagAutocompleteProps { onSelect: (val: string) => void; search: string; options: string[]; + visible: boolean; } const TagAutocomplete: VFC = ({ @@ -19,6 +20,7 @@ const TagAutocomplete: VFC = ({ onSelect, search, options, + visible, }) => { const [selected, setSelected] = useState(-1); const [categories, tags] = useMemo( @@ -82,7 +84,7 @@ const TagAutocomplete: VFC = ({ return (
void; diff --git a/src/constants/api.ts b/src/constants/api.ts index d03fdce4..a1d24d65 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -1,11 +1,11 @@ -import { IComment, INode, ITag } from '~/redux/types'; -import { ISocialProvider } from '~/redux/auth/types'; +import { IComment, INode, ITag } from '~/types'; +import { OAuthProvider } from '~/types/auth'; export const API = { BASE: process.env.REACT_APP_API_HOST, USER: { LOGIN: '/user/login', - OAUTH_WINDOW: (provider: ISocialProvider) => + OAUTH_WINDOW: (provider: OAuthProvider) => `${process.env.REACT_APP_API_HOST}oauth/${provider}/redirect`, ME: '/user/', PROFILE: (username: string) => `/user/user/${username}/profile`, diff --git a/src/constants/auth/index.ts b/src/constants/auth/index.ts new file mode 100644 index 00000000..5ea16500 --- /dev/null +++ b/src/constants/auth/index.ts @@ -0,0 +1,25 @@ +import { IUser } from '~/types/auth'; + +export enum Role { + Guest = 'guest', + User = 'user', + Admin = 'admin', +} + +export const EMPTY_USER: IUser = { + id: 0, + role: Role.Guest, + email: '', + name: '', + username: '', + photo: undefined, + cover: undefined, + is_activated: false, + is_user: false, + fullname: '', + description: '', + + last_seen: '', + last_seen_messages: '', + last_seen_boris: '', +}; diff --git a/src/constants/auth/socials.ts b/src/constants/auth/socials.ts new file mode 100644 index 00000000..3d0532f5 --- /dev/null +++ b/src/constants/auth/socials.ts @@ -0,0 +1,6 @@ +import { OAuthProvider } from '~/types/auth'; + +export const SOCIAL_ICONS: Record = { + vkontakte: 'vk', + google: 'google', +}; diff --git a/src/constants/events.ts b/src/constants/events.ts new file mode 100644 index 00000000..34cccdc6 --- /dev/null +++ b/src/constants/events.ts @@ -0,0 +1,6 @@ +export enum EventMessageType { + OpenProfile = 'open_profile', + OAuthLogin = 'oauth_login', + OAuthProcessed = 'oauth_processed', + OAuthError = 'oauth_error', +} diff --git a/src/constants/modal/index.ts b/src/constants/modal/index.ts index 5aff240f..9f7ada36 100644 --- a/src/constants/modal/index.ts +++ b/src/constants/modal/index.ts @@ -6,6 +6,9 @@ import { ProfileDialog } from '~/containers/dialogs/ProfileDialog'; import { RestoreRequestDialog } from '~/containers/dialogs/RestoreRequestDialog'; import { RestorePasswordDialog } from '~/containers/dialogs/RestorePasswordDialog'; import { PhotoSwipe } from '~/containers/dialogs/PhotoSwipe'; +import { EditorCreateDialog } from '~/containers/dialogs/EditorCreateDialog'; +import { EditorEditDialog } from '~/containers/dialogs/EditorEditDialog'; +import { TagSidebar } from '~/containers/sidebars/TagSidebar'; export enum Dialog { Login = 'Login', @@ -16,6 +19,9 @@ export enum Dialog { RestorePassword = 'RestorePassword', Test = 'Test', Photoswipe = 'Photoswipe', + CreateNode = 'CreateNode', + EditNode = 'EditNode', + TagSidebar = 'TagNodes', } export const DIALOG_CONTENT = { @@ -27,4 +33,7 @@ export const DIALOG_CONTENT = { [Dialog.RestoreRequest]: RestoreRequestDialog, [Dialog.RestorePassword]: RestorePasswordDialog, [Dialog.Photoswipe]: PhotoSwipe, + [Dialog.CreateNode]: EditorCreateDialog, + [Dialog.EditNode]: EditorEditDialog, + [Dialog.TagSidebar]: TagSidebar, } as const; diff --git a/src/constants/node/index.ts b/src/constants/node/index.ts index cc672ea9..b6075bdf 100644 --- a/src/constants/node/index.ts +++ b/src/constants/node/index.ts @@ -1,5 +1,5 @@ import { FC } from 'react'; -import { IComment, INode, ValueOf } from 'src/redux/types'; +import { IComment, INode, ValueOf } from '~/types'; import { NodeTextBlock } from '~/components/node/NodeTextBlock'; import { NodeAudioBlock } from '~/components/node/NodeAudioBlock'; import { NodeVideoBlock } from '~/components/node/NodeVideoBlock'; diff --git a/src/constants/phrases.ts b/src/constants/phrases.ts index 97a7e596..2fb4be4d 100644 --- a/src/constants/phrases.ts +++ b/src/constants/phrases.ts @@ -64,6 +64,11 @@ export const PHRASES = { 'Звук из преисподней', 'Симулятор счастливого человека', ], + REGISTER: [ + 'Сушёный кабачок особенно хорош в это время года, знаете ли.', + 'Бывало, стреляешь по кабачку, или он стреляет в тебя.', + 'Он всегда рядом, кабачок -- первый сорт! Надежда империи.', + ], }; export const getRandomPhrase = (key: keyof typeof PHRASES) => diff --git a/src/constants/uploads/index.ts b/src/constants/uploads/index.ts index 0d683b89..480256ab 100644 --- a/src/constants/uploads/index.ts +++ b/src/constants/uploads/index.ts @@ -1,4 +1,4 @@ -import { IFile } from '~/redux/types'; +import { IFile } from '~/types'; export const EMPTY_FILE: IFile = { id: undefined, diff --git a/src/constants/urls.ts b/src/constants/urls.ts index 588cf64f..e656b340 100644 --- a/src/constants/urls.ts +++ b/src/constants/urls.ts @@ -1,4 +1,4 @@ -import { INode } from '~/redux/types'; +import { INode } from '~/types'; export const URLS = { BASE: '/', diff --git a/src/containers/App.tsx b/src/containers/App.tsx index b4bf8ba8..b736931d 100644 --- a/src/containers/App.tsx +++ b/src/containers/App.tsx @@ -1,6 +1,4 @@ import React, { VFC } from 'react'; -import { ConnectedRouter } from 'connected-react-router'; -import { history } from '~/redux/store'; import { MainLayout } from '~/containers/main/MainLayout'; import { Sprites } from '~/sprites/Sprites'; import { Modal } from '~/containers/dialogs/Modal'; @@ -10,18 +8,20 @@ import { MainRouter } from '~/containers/main/MainRouter'; import { DragDetectorProvider } from '~/hooks/dom/useDragDetector'; import { UserContextProvider } from '~/utils/context/UserContextProvider'; import { SWRConfigProvider } from '~/utils/providers/SWRConfigProvider'; -import { observer } from 'mobx-react'; +import { observer } from 'mobx-react-lite'; import { useGlobalLoader } from '~/hooks/dom/useGlobalLoader'; import { SearchProvider } from '~/utils/providers/SearchProvider'; import { ToastProvider } from '~/utils/providers/ToastProvider'; import { AudioPlayerProvider } from '~/utils/providers/AudioPlayerProvider'; import { MetadataProvider } from '~/utils/providers/MetadataProvider'; +import { AuthProvider } from '~/utils/providers/AuthProvider'; +import { BrowserRouter } from 'react-router-dom'; const App: VFC = observer(() => { useGlobalLoader(); return ( - + @@ -29,14 +29,16 @@ const App: VFC = observer(() => { - - - - + + + + + - - - + + + + @@ -44,7 +46,7 @@ const App: VFC = observer(() => { - + ); }); diff --git a/src/containers/boris/BorisComments/index.tsx b/src/containers/boris/BorisComments/index.tsx index 14e7c0c4..378909f6 100644 --- a/src/containers/boris/BorisComments/index.tsx +++ b/src/containers/boris/BorisComments/index.tsx @@ -1,18 +1,21 @@ -import React, { FC } from "react"; -import styles from "./styles.module.scss"; -import { Group } from "~/components/containers/Group"; -import { NodeCommentForm } from "~/components/node/NodeCommentForm"; -import { NodeNoComments } from "~/components/node/NodeNoComments"; -import { NodeComments } from "~/containers/node/NodeComments"; -import { Footer } from "~/components/main/Footer"; -import { CommentContextProvider, useCommentContext } from "~/utils/context/CommentContextProvider"; -import { useUserContext } from "~/utils/context/UserContextProvider"; -import { useNodeContext } from "~/utils/context/NodeContextProvider"; +import React, { FC } from 'react'; +import styles from './styles.module.scss'; +import { Group } from '~/components/containers/Group'; +import { NodeCommentForm } from '~/components/node/NodeCommentForm'; +import { NodeNoComments } from '~/components/node/NodeNoComments'; +import { NodeComments } from '~/containers/node/NodeComments'; +import { Footer } from '~/components/main/Footer'; +import { CommentContextProvider, useCommentContext } from '~/utils/context/CommentContextProvider'; +import { useUserContext } from '~/utils/context/UserContextProvider'; +import { useNodeContext } from '~/utils/context/NodeContextProvider'; +import { useAuth } from '~/hooks/auth/useAuth'; interface IProps {} const BorisComments: FC = () => { const user = useUserContext(); + const { isUser } = useAuth(); + const { isLoading, comments, @@ -27,9 +30,7 @@ const BorisComments: FC = () => { return ( <> - {user.is_user && ( - - )} + {isUser && } {isLoading ? ( diff --git a/src/containers/boris/BorisComments/styles.module.scss b/src/containers/boris/BorisComments/styles.module.scss index 7662aac0..fa190d28 100644 --- a/src/containers/boris/BorisComments/styles.module.scss +++ b/src/containers/boris/BorisComments/styles.module.scss @@ -1,4 +1,4 @@ -@import "~/styles/variables.scss"; +@import "src/styles/variables.scss"; .content { flex: 4; diff --git a/src/containers/dialogs/EditorCreateDialog/index.tsx b/src/containers/dialogs/EditorCreateDialog/index.tsx index c8b5d081..31201709 100644 --- a/src/containers/dialogs/EditorCreateDialog/index.tsx +++ b/src/containers/dialogs/EditorCreateDialog/index.tsx @@ -1,30 +1,19 @@ import React, { FC, useCallback, useMemo, useRef } from 'react'; import { EMPTY_NODE, NODE_TYPES } from '~/constants/node'; import { EditorDialog } from '~/containers/dialogs/EditorDialog'; -import { useHistory, useRouteMatch } from 'react-router'; import { values } from 'ramda'; -import { INode } from '~/redux/types'; +import { INode } from '~/types'; import { useCreateNode } from '~/hooks/node/useCreateNode'; +import { DialogComponentProps } from '~/types/modal'; -const EditorCreateDialog: FC = () => { - const history = useHistory(); - const { - params: { type }, - url, - } = useRouteMatch<{ type: string }>(); - - const backUrl = useMemo(() => { - return (url && url.replace(/\/create\/(.*)$/, '')) || '/'; - }, [url]); - - const goBack = useCallback(() => { - history.replace(backUrl); - }, [backUrl, history]); +export interface EditorCreateDialogProps extends DialogComponentProps { + type: typeof NODE_TYPES[keyof typeof NODE_TYPES]; + isInLab: boolean; +} +const EditorCreateDialog: FC = ({ type, isInLab, onRequestClose }) => { const isExist = useMemo(() => values(NODE_TYPES).some(el => el === type), [type]); - const isInLab = useMemo(() => !!url.match(/^\/lab/), [url]); - const data = useRef({ ...EMPTY_NODE, type, is_promoted: !isInLab }); const createNode = useCreateNode(); @@ -32,16 +21,16 @@ const EditorCreateDialog: FC = () => { const onSubmit = useCallback( async (node: INode) => { await createNode(node); - goBack(); + onRequestClose(); }, - [goBack, createNode] + [onRequestClose, createNode] ); if (!type || !isExist) { return null; } - return ; + return ; }; export { EditorCreateDialog }; diff --git a/src/containers/dialogs/EditorDialog/index.tsx b/src/containers/dialogs/EditorDialog/index.tsx index 7fccfac1..29764c95 100644 --- a/src/containers/dialogs/EditorDialog/index.tsx +++ b/src/containers/dialogs/EditorDialog/index.tsx @@ -1,22 +1,20 @@ -import React, { createElement, FC, useCallback, useMemo, useState } from "react"; -import styles from "./styles.module.scss"; -import { NODE_EDITORS } from "~/constants/node"; -import { BetterScrollDialog } from "../BetterScrollDialog"; -import { CoverBackdrop } from "~/components/containers/CoverBackdrop"; -import { prop } from "ramda"; -import { useNodeFormFormik } from "~/hooks/node/useNodeFormFormik"; -import { EditorButtons } from "~/components/editors/EditorButtons"; -import { UploadSubject, UploadTarget } from "~/constants/uploads"; -import { FormikProvider } from "formik"; -import { INode } from "~/redux/types"; -import { ModalWrapper } from "~/components/dialogs/ModalWrapper"; -import { useTranslatedError } from "~/hooks/data/useTranslatedError"; -import { useCloseOnEscape } from "~/hooks"; -import { EditorConfirmClose } from "~/components/editors/EditorConfirmClose"; -import { DialogComponentProps } from "~/types/modal"; -import { useUploader } from "~/hooks/data/useUploader"; -import { UploaderContextProvider } from "~/utils/context/UploaderContextProvider"; -import { observer } from "mobx-react-lite"; +import React, { createElement, FC, useCallback, useMemo, useState } from 'react'; +import styles from './styles.module.scss'; +import { NODE_EDITORS } from '~/constants/node'; +import { BetterScrollDialog } from '~/components/dialogs/BetterScrollDialog'; +import { CoverBackdrop } from '~/components/containers/CoverBackdrop'; +import { prop } from 'ramda'; +import { useNodeFormFormik } from '~/hooks/node/useNodeFormFormik'; +import { EditorButtons } from '~/components/editors/EditorButtons'; +import { UploadSubject, UploadTarget } from '~/constants/uploads'; +import { FormikProvider } from 'formik'; +import { INode } from '~/types'; +import { useCloseOnEscape } from '~/hooks'; +import { EditorConfirmClose } from '~/components/editors/EditorConfirmClose'; +import { DialogComponentProps } from '~/types/modal'; +import { useUploader } from '~/hooks/data/useUploader'; +import { UploaderContextProvider } from '~/utils/context/UploaderContextProvider'; +import { observer } from 'mobx-react-lite'; interface Props extends DialogComponentProps { node: INode; @@ -50,8 +48,6 @@ const EditorDialog: FC = observer(({ node, onRequestClose, onSubmit }) => setConfirmModalShown(true); }, [dirty, isConfirmModalShown, onRequestClose, closeConfirmModal]); - const error = useTranslatedError(status); - useCloseOnEscape(onClose); if (!component) { @@ -59,29 +55,26 @@ const EditorDialog: FC = observer(({ node, onRequestClose, onSubmit }) => } return ( - - - -
- } - backdrop={} - width={860} - error={error} - onClose={onClose} - > - <> - {isConfirmModalShown && ( - - )} + + + + } + backdrop={} + width={860} + onClose={onClose} + > + <> + {isConfirmModalShown && ( + + )} -
{createElement(component)}
- -
- -
-
-
+
{createElement(component)}
+ + + + + ); }); diff --git a/src/containers/dialogs/EditorEditDialog/index.tsx b/src/containers/dialogs/EditorEditDialog/index.tsx index 885a10e5..a64e3366 100644 --- a/src/containers/dialogs/EditorEditDialog/index.tsx +++ b/src/containers/dialogs/EditorEditDialog/index.tsx @@ -1,44 +1,33 @@ -import React, { FC, useCallback, useMemo } from 'react'; +import React, { FC, useCallback } from 'react'; import { EditorDialog } from '~/containers/dialogs/EditorDialog'; -import { useHistory, useRouteMatch } from 'react-router'; import { ModalWrapper } from '~/components/dialogs/ModalWrapper'; import { LoaderCircle } from '~/components/input/LoaderCircle'; import styles from './styles.module.scss'; import { useLoadNode } from '~/hooks/node/useLoadNode'; import { useUpdateNode } from '~/hooks/node/useUpdateNode'; -import { INode } from '~/redux/types'; -import { observer } from 'mobx-react'; +import { INode } from '~/types'; +import { observer } from 'mobx-react-lite'; +import { DialogComponentProps } from '~/types/modal'; -const EditorEditDialog: FC = observer(() => { - const history = useHistory(); +export interface EditorEditDialogProps extends DialogComponentProps { + nodeId: number; +} - const { - params: { id }, - url, - } = useRouteMatch<{ id: string }>(); - - const backUrl = useMemo(() => { - return url.replace(/\/edit$/, ''); - }, [url]); - - const goBack = useCallback(() => { - history.replace(backUrl); - }, [backUrl, history]); - - const { node, isLoading } = useLoadNode(parseInt(id, 10)); - const updateNode = useUpdateNode(parseInt(id, 10)); +const EditorEditDialog: FC = observer(({ nodeId, onRequestClose }) => { + const { node, isLoading } = useLoadNode(nodeId); + const updateNode = useUpdateNode(nodeId); const onSubmit = useCallback( async (node: INode) => { await updateNode(node); - goBack(); + onRequestClose(); }, - [updateNode, goBack] + [updateNode, onRequestClose] ); if (isLoading || !node) { return ( - +
@@ -46,7 +35,7 @@ const EditorEditDialog: FC = observer(() => { ); } - return ; + return ; }); export { EditorEditDialog }; diff --git a/src/containers/dialogs/LoginDialog/index.tsx b/src/containers/dialogs/LoginDialog/index.tsx index 4f9aa06e..5f54a9bb 100644 --- a/src/containers/dialogs/LoginDialog/index.tsx +++ b/src/containers/dialogs/LoginDialog/index.tsx @@ -1,62 +1,29 @@ -import React, { FC, FormEvent, useCallback, useEffect, useState } from 'react'; -import { connect } from 'react-redux'; +import React, { FC, useCallback } from 'react'; import { useCloseOnEscape } from '~/hooks'; import { Group } from '~/components/containers/Group'; import { InputText } from '~/components/input/InputText'; import { Button } from '~/components/input/Button'; import { Padder } from '~/components/containers/Padder'; -import { selectAuthLogin } from '~/redux/auth/selectors'; -import { API } from '~/constants/api'; -import { BetterScrollDialog } from '../BetterScrollDialog'; +import { BetterScrollDialog } from '~/components/dialogs/BetterScrollDialog'; import styles from './styles.module.scss'; -import * as ACTIONS from '~/redux/auth/actions'; -import { ISocialProvider } from '~/redux/auth/types'; -import { pick } from 'ramda'; -import { LoginDialogButtons } from '~/containers/dialogs/LoginDialogButtons'; -import { OAUTH_EVENT_TYPES } from '~/redux/types'; +import { LoginDialogButtons } from '~/components/auth/login/LoginDialogButtons'; import { DialogTitle } from '~/components/dialogs/DialogTitle'; -import { useTranslatedError } from '~/hooks/data/useTranslatedError'; import { DialogComponentProps } from '~/types/modal'; import { useShowModal } from '~/hooks/modal/useShowModal'; import { Dialog } from '~/constants/modal'; +import { useAuth } from '~/hooks/auth/useAuth'; +import { useLoginForm } from '~/hooks/auth/useLoginForm'; +import { useOAuth } from '~/hooks/auth/useOAuth'; -const mapStateToProps = state => ({ - ...pick(['error', 'is_registering'], selectAuthLogin(state)), -}); +type LoginDialogProps = DialogComponentProps & {}; -const mapDispatchToProps = { - userSendLoginRequest: ACTIONS.userSendLoginRequest, - userSetLoginError: ACTIONS.userSetLoginError, - authLoginWithSocial: ACTIONS.authLoginWithSocial, - authGotOauthLoginEvent: ACTIONS.authGotOauthLoginEvent, -}; - -type IProps = ReturnType & - typeof mapDispatchToProps & - DialogComponentProps & {}; - -const LoginDialogUnconnected: FC = ({ - error, - - onRequestClose, - userSendLoginRequest, - userSetLoginError, - authGotOauthLoginEvent, -}) => { - const [username, setUserName] = useState(''); - const [password, setPassword] = useState(''); +const LoginDialog: FC = ({ onRequestClose }) => { + useCloseOnEscape(onRequestClose); + const { login } = useAuth(); + const { openOauthWindow } = useOAuth(); const showRestoreDialog = useShowModal(Dialog.RestoreRequest); - - const onSubmit = useCallback( - (event: FormEvent) => { - event.preventDefault(); - userSendLoginRequest({ username, password }); - }, - [userSendLoginRequest, username, password] - ); - const onRestoreRequest = useCallback( event => { event.preventDefault(); @@ -65,44 +32,13 @@ const LoginDialogUnconnected: FC = ({ [showRestoreDialog] ); - const openOauthWindow = useCallback( - (provider: ISocialProvider) => () => { - window.open(API.USER.OAUTH_WINDOW(provider), '', 'width=600,height=400'); - }, - [] - ); - - const onMessage = useCallback( - (event: MessageEvent) => { - if (!event?.data?.type || !Object.values(OAUTH_EVENT_TYPES).includes(event.data.type)) { - return; - } - - authGotOauthLoginEvent(event.data); - }, - [authGotOauthLoginEvent] - ); - - useEffect(() => { - if (error) userSetLoginError(''); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [username, password]); - - useEffect(() => { - window.addEventListener('message', onMessage); - return () => window.removeEventListener('message', onMessage); - }, [onMessage]); - - useCloseOnEscape(onRequestClose); - - const translatedError = useTranslatedError(error); + const { values, errors, handleSubmit, handleChange } = useLoginForm(login, onRequestClose); return ( -
+
} backdrop={
} @@ -112,9 +48,21 @@ const LoginDialogUnconnected: FC = ({ Решительно войти - + - + - - - - - - - -); - -export { LoginDialogButtons }; diff --git a/src/containers/dialogs/LoginSocialRegisterButtons/index.tsx b/src/containers/dialogs/LoginSocialRegisterButtons/index.tsx deleted file mode 100644 index f0f856e9..00000000 --- a/src/containers/dialogs/LoginSocialRegisterButtons/index.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React, { FC } from "react"; -import { Button } from "~/components/input/Button"; -import styles from "./styles.module.scss"; - -interface IProps {} - -const LoginSocialRegisterButtons: FC = () => ( -
- -
-); - -export { LoginSocialRegisterButtons }; diff --git a/src/containers/dialogs/LoginSocialRegisterDialog/index.tsx b/src/containers/dialogs/LoginSocialRegisterDialog/index.tsx index 2f0f1819..8595502c 100644 --- a/src/containers/dialogs/LoginSocialRegisterDialog/index.tsx +++ b/src/containers/dialogs/LoginSocialRegisterDialog/index.tsx @@ -1,76 +1,52 @@ -import React, { FC, FormEvent, useCallback, useEffect, useState } from 'react'; -import { connect } from 'react-redux'; -import { BetterScrollDialog } from '~/containers/dialogs/BetterScrollDialog'; +import React, { FC, useCallback, useState } from 'react'; +import { BetterScrollDialog } from '~/components/dialogs/BetterScrollDialog'; import { Padder } from '~/components/containers/Padder'; import { DialogTitle } from '~/components/dialogs/DialogTitle'; import { Group } from '~/components/containers/Group'; import { InputText } from '~/components/input/InputText'; import styles from './styles.module.scss'; -import { selectAuthRegisterSocial } from '~/redux/auth/selectors'; -import * as AUTH_ACTIONS from '~/redux/auth/actions'; import { useCloseOnEscape } from '~/hooks'; -import { LoginSocialRegisterButtons } from '~/containers/dialogs/LoginSocialRegisterButtons'; +import { LoginSocialRegisterButtons } from '~/components/auth/oauth/LoginSocialRegisterButtons'; import { Toggle } from '~/components/input/Toggle'; import { DialogComponentProps } from '~/types/modal'; +import { getRandomPhrase } from '~/constants/phrases'; +import { useSocialRegisterForm } from '~/hooks/auth/useSocialRegisterForm'; +import { apiLoginWithSocial } from '~/api/auth'; +import { useModal } from '~/hooks/modal/useModal'; +import { useAuthStore } from '~/store/auth/useAuthStore'; -const mapStateToProps = selectAuthRegisterSocial; -const mapDispatchToProps = { - authSetRegisterSocialErrors: AUTH_ACTIONS.authSetRegisterSocialErrors, - authSetRegisterSocial: AUTH_ACTIONS.authSetRegisterSocial, - authSendRegisterSocial: AUTH_ACTIONS.authSendRegisterSocial, -}; +type LoginSocialRegisterDialogProps = DialogComponentProps & { token: string }; -type Props = ReturnType & - typeof mapDispatchToProps & - DialogComponentProps & {}; +const phrase = getRandomPhrase('REGISTER'); -const phrase = [ - 'Сушёный кабачок особенно хорош в это время года, знаете ли.', - 'Бывало, стреляешь по кабачку, или он стреляет в тебя.', - 'Он всегда рядом, кабачок -- первый сорт! Надежда империи.', -]; - -const LoginSocialRegisterDialogUnconnected: FC = ({ +const LoginSocialRegisterDialog: FC = ({ onRequestClose, - errors, - error, - - authSetRegisterSocialErrors, - authSetRegisterSocial, - authSendRegisterSocial, + token, }) => { - const [username, setUsername] = useState(''); - const [password, setPassword] = useState(''); - const [isDryingPants, setIsDryingPants] = useState(false); + useCloseOnEscape(onRequestClose); + const { hideModal } = useModal(); + const auth = useAuthStore(); - const onSubmit = useCallback( - (event: FormEvent) => { - event.preventDefault(); - authSendRegisterSocial(username, password); + const [isDryingPants, setIsDryingPants] = useState(false); + const onSuccess = useCallback( + (loginToken: string) => { + auth.setToken(loginToken); + hideModal(); }, - [username, password, authSendRegisterSocial] + [auth, hideModal] ); - useEffect(() => { - if (errors.username) authSetRegisterSocialErrors({ username: '' }); - }, [authSetRegisterSocialErrors, errors.username, username]); - - useEffect(() => { - if (errors.password) authSetRegisterSocialErrors({ password: '' }); - }, [authSetRegisterSocialErrors, errors.password, password]); - - useEffect(() => { - if (error) authSetRegisterSocial({ error: '' }); - }, [username, password, error, authSetRegisterSocial]); - - useCloseOnEscape(onRequestClose); + const { values, errors, handleChange, handleSubmit } = useSocialRegisterForm( + token, + apiLoginWithSocial, + onSuccess + ); return ( - + } > @@ -79,16 +55,16 @@ const LoginSocialRegisterDialogUnconnected: FC = ({ Добро пожаловать в семью! = ({
setIsDryingPants(!isDryingPants)}> - {phrase[Math.floor(Math.random() * phrase.length)]} + {phrase}
@@ -112,9 +88,4 @@ const LoginSocialRegisterDialogUnconnected: FC = ({ ); }; -const LoginSocialRegisterDialog = connect( - mapStateToProps, - mapDispatchToProps -)(LoginSocialRegisterDialogUnconnected); - export { LoginSocialRegisterDialog }; diff --git a/src/containers/dialogs/Modal/index.tsx b/src/containers/dialogs/Modal/index.tsx index b1515cd5..ecbbc50a 100644 --- a/src/containers/dialogs/Modal/index.tsx +++ b/src/containers/dialogs/Modal/index.tsx @@ -1,9 +1,9 @@ -import React, { FC } from "react"; -import { ModalWrapper } from "~/components/dialogs/ModalWrapper"; -import { DIALOG_CONTENT } from "~/constants/modal"; -import { useModalStore } from "~/store/modal/useModalStore"; -import { has } from "ramda"; -import { observer } from "mobx-react-lite"; +import React, { FC } from 'react'; +import { ModalWrapper } from '~/components/dialogs/ModalWrapper'; +import { DIALOG_CONTENT } from '~/constants/modal'; +import { useModalStore } from '~/store/modal/useModalStore'; +import { has } from 'ramda'; +import { observer } from 'mobx-react-lite'; type IProps = {}; diff --git a/src/containers/dialogs/PhotoSwipe/index.tsx b/src/containers/dialogs/PhotoSwipe/index.tsx index 46f4c658..8a534e27 100644 --- a/src/containers/dialogs/PhotoSwipe/index.tsx +++ b/src/containers/dialogs/PhotoSwipe/index.tsx @@ -6,10 +6,9 @@ import { getURL } from '~/utils/dom'; import { PRESETS } from '~/constants/urls'; import styles from './styles.module.scss'; import classNames from 'classnames'; -import { useBlockBackButton } from '~/hooks/navigation/useBlockBackButton'; import { useModal } from '~/hooks/modal/useModal'; -import { observer } from 'mobx-react'; -import { IFile } from '~/redux/types'; +import { observer } from 'mobx-react-lite'; +import { IFile } from '~/types'; import { DialogComponentProps } from '~/types/modal'; export interface PhotoSwipeProps extends DialogComponentProps { @@ -60,8 +59,6 @@ const PhotoSwipe: VFC = observer(({ index, items }) => { }); }, [hideModal, items, index]); - useBlockBackButton(hideModal); - return (