mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
removed node reducer
This commit is contained in:
parent
168ba8cc04
commit
8d2b56cafc
14 changed files with 62 additions and 208 deletions
|
@ -1,27 +0,0 @@
|
|||
import React, { FC, memo } from 'react';
|
||||
import styles from './styles.module.scss';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { selectNode } from '~/redux/node/selectors';
|
||||
import { connect } from 'react-redux';
|
||||
import { pick } from 'ramda';
|
||||
import { getURL } from '~/utils/dom';
|
||||
import { PRESETS } from '~/constants/urls';
|
||||
|
||||
const mapStateToProps = state => pick(['current_cover_image'], selectNode(state));
|
||||
|
||||
type IProps = ReturnType<typeof mapStateToProps> & {};
|
||||
|
||||
const PageCoverUnconnected: FC<IProps> = memo(({ current_cover_image }) =>
|
||||
current_cover_image
|
||||
? createPortal(
|
||||
<div
|
||||
className={styles.wrap}
|
||||
style={{ backgroundImage: `url("${getURL(current_cover_image, PRESETS.cover)}")` }}
|
||||
/>,
|
||||
document.body
|
||||
)
|
||||
: null
|
||||
);
|
||||
|
||||
const PageCover = connect(mapStateToProps)(PageCoverUnconnected);
|
||||
export { PageCover };
|
39
src/components/containers/PageCoverProvider/index.tsx
Normal file
39
src/components/containers/PageCoverProvider/index.tsx
Normal file
|
@ -0,0 +1,39 @@
|
|||
import React, { createContext, FC, memo, useContext, useState } from 'react';
|
||||
import styles from './styles.module.scss';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { getURL } from '~/utils/dom';
|
||||
import { PRESETS } from '~/constants/urls';
|
||||
import { IFile } from '~/redux/types';
|
||||
|
||||
interface CoverContextValue {
|
||||
cover: IFile | null;
|
||||
setCover: (cover: IFile | null) => void;
|
||||
}
|
||||
|
||||
const CoverContext = createContext<CoverContextValue>({
|
||||
cover: null,
|
||||
setCover: () => {},
|
||||
});
|
||||
|
||||
const PageCoverProvider: FC = ({ children }) => {
|
||||
const [cover, setCover] = useState<IFile | null>(null);
|
||||
|
||||
return (
|
||||
<CoverContext.Provider value={{ cover, setCover }}>
|
||||
{!!cover &&
|
||||
createPortal(
|
||||
<div
|
||||
className={styles.wrap}
|
||||
style={{ backgroundImage: `url("${getURL(cover, PRESETS.cover)}")` }}
|
||||
/>,
|
||||
document.body
|
||||
)}
|
||||
|
||||
{children}
|
||||
</CoverContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const usePageCoverContext = () => useContext(CoverContext);
|
||||
|
||||
export { PageCoverProvider, usePageCoverContext };
|
12
src/components/containers/PageCoverProvider/usePageCover.ts
Normal file
12
src/components/containers/PageCoverProvider/usePageCover.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { useEffect } from 'react';
|
||||
import { IFile } from '~/redux/types';
|
||||
import { usePageCoverContext } from '~/components/containers/PageCoverProvider/index';
|
||||
|
||||
export const usePageCover = (cover?: IFile) => {
|
||||
const { setCover } = usePageCoverContext();
|
||||
|
||||
useEffect(() => {
|
||||
setCover(cover || null);
|
||||
return () => setCover(null);
|
||||
}, [setCover, cover]);
|
||||
};
|
|
@ -4,7 +4,7 @@ import { history } from '~/redux/store';
|
|||
import { MainLayout } from '~/containers/main/MainLayout';
|
||||
import { Sprites } from '~/sprites/Sprites';
|
||||
import { Modal } from '~/containers/dialogs/Modal';
|
||||
import { PageCover } from '~/components/containers/PageCover';
|
||||
import { PageCoverProvider } from '~/components/containers/PageCoverProvider';
|
||||
import { BottomContainer } from '~/containers/main/BottomContainer';
|
||||
import { MainRouter } from '~/containers/main/MainRouter';
|
||||
import { DragDetectorProvider } from '~/hooks/dom/useDragDetector';
|
||||
|
@ -20,8 +20,7 @@ const App: VFC = () => {
|
|||
<SWRConfigProvider>
|
||||
<UserContextProvider user={user}>
|
||||
<DragDetectorProvider>
|
||||
<PageCover />
|
||||
|
||||
<PageCoverProvider>
|
||||
<MainLayout>
|
||||
<Modal />
|
||||
<Sprites />
|
||||
|
@ -29,6 +28,7 @@ const App: VFC = () => {
|
|||
<MainRouter />
|
||||
</MainLayout>
|
||||
<BottomContainer />
|
||||
</PageCoverProvider>
|
||||
</DragDetectorProvider>
|
||||
</UserContextProvider>
|
||||
</SWRConfigProvider>
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
import React, { FC, useEffect, useState } from 'react';
|
||||
import { RouteComponentProps, useRouteMatch, withRouter } from 'react-router';
|
||||
import styles from './styles.module.scss';
|
||||
import { NodeNoComments } from '~/components/node/NodeNoComments';
|
||||
import { Grid } from '~/components/containers/Grid';
|
||||
import * as NODE_ACTIONS from '~/redux/node/actions';
|
||||
import { connect } from 'react-redux';
|
||||
import { IUser } from '~/redux/auth/types';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { CommentForm } from '~/components/comment/CommentForm';
|
||||
|
||||
const mapStateToProps = () => ({});
|
||||
const mapDispatchToProps = {
|
||||
nodeSetCoverImage: NODE_ACTIONS.nodeSetCoverImage,
|
||||
};
|
||||
|
||||
type IProps = RouteComponentProps & typeof mapDispatchToProps & {};
|
||||
|
||||
const ProfileLayoutUnconnected: FC<IProps> = ({ history, nodeSetCoverImage }) => {
|
||||
const {
|
||||
params: { username },
|
||||
} = useRouteMatch<{ username: string }>();
|
||||
const [user, setUser] = useState<IUser | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (user) setUser(undefined);
|
||||
}, [user, username]);
|
||||
|
||||
useEffect(() => {
|
||||
if (user && user.id && user.cover) {
|
||||
nodeSetCoverImage(user.cover);
|
||||
return () => {
|
||||
nodeSetCoverImage(undefined);
|
||||
};
|
||||
}
|
||||
}, [nodeSetCoverImage, user]);
|
||||
|
||||
return (
|
||||
<Group className={styles.wrap} horizontal>
|
||||
<div className={styles.column} />
|
||||
|
||||
<Grid className={styles.content}>
|
||||
<div className={styles.comments}>
|
||||
<CommentForm nodeId={0} saveComment={async () => console.log()} />
|
||||
<NodeNoComments is_loading={false} />
|
||||
</div>
|
||||
</Grid>
|
||||
</Group>
|
||||
);
|
||||
};
|
||||
|
||||
const ProfileLayout = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(withRouter(ProfileLayoutUnconnected));
|
||||
|
||||
export { ProfileLayout };
|
|
@ -1,29 +0,0 @@
|
|||
@import "src/styles/variables";
|
||||
|
||||
.wrap {
|
||||
display: flex;
|
||||
align-items: flex-start !important;
|
||||
justify-content: flex-start !important;
|
||||
flex-direction: row;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 3;
|
||||
// flex: 0 1 $limited_width;
|
||||
// padding: $gap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.column {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info {
|
||||
}
|
||||
|
||||
.comments {
|
||||
background: $node_bg;
|
||||
border-radius: $radius;
|
||||
padding: $gap;
|
||||
}
|
|
@ -1,16 +1,6 @@
|
|||
import { INode } from '~/redux/types';
|
||||
import { useEffect } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { nodeSetCoverImage } from '~/redux/node/actions';
|
||||
import { usePageCover } from '~/components/containers/PageCoverProvider/usePageCover';
|
||||
|
||||
export const useNodeCoverImage = (node: INode) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(nodeSetCoverImage(node.cover));
|
||||
|
||||
return () => {
|
||||
dispatch(nodeSetCoverImage(undefined));
|
||||
};
|
||||
}, [dispatch, node.cover, node.id]);
|
||||
usePageCover(node.cover);
|
||||
};
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
import { IFile } from '../types';
|
||||
import { NODE_ACTIONS } from './constants';
|
||||
|
||||
export const nodeSetCoverImage = (current_cover_image?: IFile) => ({
|
||||
type: NODE_ACTIONS.SET_COVER_IMAGE,
|
||||
current_cover_image,
|
||||
});
|
|
@ -23,11 +23,6 @@ import { LabDescription } from '~/components/lab/LabDescription';
|
|||
import { LabVideo } from '~/components/lab/LabVideo';
|
||||
import { LabAudio } from '~/components/lab/LabAudioBlock';
|
||||
|
||||
const prefix = 'NODE.';
|
||||
export const NODE_ACTIONS = {
|
||||
SET_COVER_IMAGE: `${prefix}SET_COVER_IMAGE`,
|
||||
};
|
||||
|
||||
export const EMPTY_NODE: INode = {
|
||||
id: 0,
|
||||
user: undefined,
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import { assocPath } from 'ramda';
|
||||
import { NODE_ACTIONS } from './constants';
|
||||
import { nodeSetCoverImage } from './actions';
|
||||
import { INodeState } from './reducer';
|
||||
|
||||
const setCoverImage = (
|
||||
state: INodeState,
|
||||
{ current_cover_image }: ReturnType<typeof nodeSetCoverImage>
|
||||
) => assocPath(['current_cover_image'], current_cover_image, state);
|
||||
|
||||
export const NODE_HANDLERS = {
|
||||
[NODE_ACTIONS.SET_COVER_IMAGE]: setCoverImage,
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
import { createReducer } from '~/utils/reducer';
|
||||
import { IComment, IFile, INode } from '../types';
|
||||
import { EMPTY_NODE } from './constants';
|
||||
import { NODE_HANDLERS } from './handlers';
|
||||
|
||||
export type INodeState = Readonly<{
|
||||
editor: INode;
|
||||
current: INode;
|
||||
comments: IComment[];
|
||||
lastSeenCurrent?: string;
|
||||
comment_count: number;
|
||||
current_cover_image?: IFile;
|
||||
|
||||
error: string;
|
||||
errors: Record<string, string>;
|
||||
|
||||
is_loading: boolean;
|
||||
is_loading_comments: boolean;
|
||||
is_sending_comment: boolean;
|
||||
}>;
|
||||
|
||||
const INITIAL_STATE: INodeState = {
|
||||
editor: {
|
||||
...EMPTY_NODE,
|
||||
type: 'image',
|
||||
blocks: [],
|
||||
files: [],
|
||||
},
|
||||
current: { ...EMPTY_NODE },
|
||||
comment_count: 0,
|
||||
comments: [],
|
||||
current_cover_image: undefined,
|
||||
|
||||
is_loading: false,
|
||||
is_loading_comments: false,
|
||||
is_sending_comment: false,
|
||||
|
||||
error: '',
|
||||
errors: {},
|
||||
};
|
||||
|
||||
export default createReducer(INITIAL_STATE, NODE_HANDLERS);
|
|
@ -1,3 +0,0 @@
|
|||
import { IState } from '../store';
|
||||
|
||||
export const selectNode = (state: IState) => state.node;
|
|
@ -11,8 +11,6 @@ import auth from '~/redux/auth';
|
|||
import authSaga from '~/redux/auth/sagas';
|
||||
import { IAuthState } from '~/redux/auth/types';
|
||||
|
||||
import node, { INodeState } from '~/redux/node/reducer';
|
||||
|
||||
import flow, { IFlowState } from '~/redux/flow/reducer';
|
||||
import flowSaga from '~/redux/flow/sagas';
|
||||
|
||||
|
@ -65,7 +63,6 @@ export interface IState {
|
|||
auth: IAuthState;
|
||||
modal: IModalState;
|
||||
router: RouterState;
|
||||
node: INodeState;
|
||||
uploads: IUploadState;
|
||||
flow: IFlowState;
|
||||
player: IPlayerState;
|
||||
|
@ -91,7 +88,6 @@ export const store = createStore(
|
|||
modal,
|
||||
boris,
|
||||
router: connectRouter(history),
|
||||
node,
|
||||
uploads,
|
||||
flow: persistReducer(flowPersistConfig, flow),
|
||||
player: persistReducer(playerPersistConfig, player),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue