diff --git a/.eslintrc.js b/.eslintrc.js index dd724fe8..944a5dd1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -52,7 +52,8 @@ module.exports = { "exports": "always-multiline", "functions": "never" }], - indent: "off" + indent: "off", + "import/order": "off" }, globals: { document: false, diff --git a/src/components/flow/Cell/index.tsx b/src/components/flow/Cell/index.tsx index 6c1cf034..2aaa7b60 100644 --- a/src/components/flow/Cell/index.tsx +++ b/src/components/flow/Cell/index.tsx @@ -14,18 +14,18 @@ interface IProps { // title?: string; // is_hero?: boolean; // is_stamp?: boolean; - onSelect: (id: INode['id']) => void; + onSelect: (id: INode['id'], type: INode['type']) => void; is_text?: boolean; } -const Cell: FC = ({ node: { id, title, brief }, onSelect, is_text = false }) => { +const Cell: FC = ({ node: { id, title, brief, type }, onSelect, is_text = false }) => { const [is_loaded, setIsLoaded] = useState(false); const onImageLoad = useCallback(() => { setIsLoaded(true); }, [setIsLoaded]); - const onClick = useCallback(() => onSelect(id), [onSelect, id]); + const onClick = useCallback(() => onSelect(id, type), [onSelect, id]); return (
& { - onSelect: (id: INode['id']) => void; + onSelect: (id: INode['id'], type: INode['type']) => void; }; export const FlowGrid: FC = ({ nodes, onSelect }) => ( diff --git a/src/components/node/NodeImageBlock/index.tsx b/src/components/node/NodeImageBlock/index.tsx index 07380f11..72a364d8 100644 --- a/src/components/node/NodeImageBlock/index.tsx +++ b/src/components/node/NodeImageBlock/index.tsx @@ -1,21 +1,41 @@ -import React, { FC } from 'react'; +import React, { FC, useMemo } from 'react'; import { ImageSwitcher } from '../ImageSwitcher'; import * as styles from './styles.scss'; +import { INode } from '~/redux/types'; +import classNames from 'classnames'; +import { getImageSize } from '~/utils/dom'; +import { UPLOAD_TYPES } from '~/redux/uploads/constants'; -interface IProps {} +interface IProps { + is_loading: boolean; + node: INode; +} -const NodeImageBlock: FC = ({}) => ( -
- +const NodeImageBlock: FC = ({ node, is_loading }) => { + const images = useMemo(() => node.files.filter(({ type }) => type === UPLOAD_TYPES.IMAGE), [ + node, + ]); -
- + return ( +
+ {!is_loading && ( +
+ + +
+ {images.map(file => ( + + ))} +
+
+ )}
-
-); + ); +}; export { NodeImageBlock }; diff --git a/src/containers/node/NodeLayout/index.tsx b/src/containers/node/NodeLayout/index.tsx index 644c8827..699901d5 100644 --- a/src/containers/node/NodeLayout/index.tsx +++ b/src/containers/node/NodeLayout/index.tsx @@ -14,9 +14,12 @@ import * as styles from './styles.scss'; import { NodeComments } from '~/components/node/NodeComments'; import { NodeTags } from '~/components/node/NodeTags'; import { NODE_COMPONENTS } from '~/redux/node/constants'; +import * as NODE_ACTIONS from '~/redux/node/actions'; const mapStateToProps = selectNode; -const mapDispatchToProps = {}; +const mapDispatchToProps = { + nodeLoadNode: NODE_ACTIONS.nodeLoadNode, +}; type IProps = ReturnType & typeof mapDispatchToProps & @@ -28,22 +31,23 @@ const NodeLayoutUnconnected: FC = ({ }, is_loading, current: node, + nodeLoadNode, }) => { useEffect(() => { - // if (is_loading) return; + if (is_loading) return; + nodeLoadNode(id, null); // todo: if node not loading, load it! }, []); useEffect(() => console.log({ is_loading }), [is_loading]); const block = node && node.type && NODE_COMPONENTS[node.type] && NODE_COMPONENTS[node.type]; - const view = block && block[is_loading ? 'placeholder' : 'component']; - - console.log({ block, view }); + // const view = block && block[is_loading ? 'placeholder' : 'component']; + // console.log({ block, view }); return ( - {view && createElement(view, { node })} + {block && createElement(block, { node, is_loading })} diff --git a/src/redux/node/actions.ts b/src/redux/node/actions.ts index a55c2761..ac40d4f6 100644 --- a/src/redux/node/actions.ts +++ b/src/redux/node/actions.ts @@ -12,8 +12,9 @@ export const nodeSetSaveErrors = (errors: IValidationErrors) => ({ type: NODE_ACTIONS.SET_SAVE_ERRORS, }); -export const nodeLoadNode = (id: string | number) => ({ +export const nodeLoadNode = (id: string | number, node_type: INode['type']) => ({ id, + node_type, type: NODE_ACTIONS.LOAD_NODE, }); @@ -21,3 +22,8 @@ export const nodeSetLoading = (is_loading: INodeState['is_loading']) => ({ is_loading, type: NODE_ACTIONS.SET_LOADING, }); + +export const nodeSetCurrent = (current: INodeState['current']) => ({ + current, + type: NODE_ACTIONS.SET_CURRENT, +}); diff --git a/src/redux/node/constants.ts b/src/redux/node/constants.ts index afbd2019..73260596 100644 --- a/src/redux/node/constants.ts +++ b/src/redux/node/constants.ts @@ -1,15 +1,16 @@ +import { FC } from 'react'; import { IBlock, INode, ValueOf } from '../types'; import { NodeImageBlock } from '~/components/node/NodeImageBlock'; import { NodeImageBlockPlaceholder } from '~/components/node/NodeImageBlockPlaceholder'; -import { ReactElement, FC } from 'react'; const prefix = 'NODE.'; export const NODE_ACTIONS = { - SAVE: `${prefix}NODE.SAVE`, + SAVE: `${prefix}SAVE`, LOAD_NODE: `${prefix}LOAD_NODE`, - SET_SAVE_ERRORS: `${prefix}NODE.SET_SAVE_ERRORS`, - SET_LOADING: `${prefix}NODE.SET_LOADING`, + SET_SAVE_ERRORS: `${prefix}SET_SAVE_ERRORS`, + SET_LOADING: `${prefix}SET_LOADING`, + SET_CURRENT: `${prefix}SET_CURRENT`, }; export const EMPTY_BLOCK: IBlock = { @@ -47,14 +48,8 @@ export const NODE_TYPES = { TEXT: 'text', }; -type INodeComponents = Record< - ValueOf, - Record<'component' | 'placeholder', FC<{ node: INode }>> ->; +type INodeComponents = Record, FC<{ node: INode; is_loading: boolean }>>; export const NODE_COMPONENTS: INodeComponents = { - [NODE_TYPES.IMAGE]: { - component: NodeImageBlock, - placeholder: NodeImageBlockPlaceholder, - }, + [NODE_TYPES.IMAGE]: NodeImageBlock, }; diff --git a/src/redux/node/handlers.ts b/src/redux/node/handlers.ts index 00a59f07..d2e43f00 100644 --- a/src/redux/node/handlers.ts +++ b/src/redux/node/handlers.ts @@ -1,6 +1,6 @@ import assocPath from 'ramda/es/assocPath'; import { NODE_ACTIONS } from './constants'; -import { nodeSetSaveErrors, nodeSetLoading } from './actions'; +import { nodeSetSaveErrors, nodeSetLoading, nodeSetCurrent } from './actions'; import { INodeState } from './reducer'; const setSaveErrors = (state: INodeState, { errors }: ReturnType) => @@ -9,7 +9,11 @@ const setSaveErrors = (state: INodeState, { errors }: ReturnType) => assocPath(['is_loading'], is_loading, state); +const setCurrent = (state: INodeState, { current }: ReturnType) => + assocPath(['current'], current, state); + export const NODE_HANDLERS = { [NODE_ACTIONS.SAVE]: setSaveErrors, [NODE_ACTIONS.SET_LOADING]: setLoading, + [NODE_ACTIONS.SET_CURRENT]: setCurrent, }; diff --git a/src/redux/node/sagas.ts b/src/redux/node/sagas.ts index b4055232..2bc3e1aa 100644 --- a/src/redux/node/sagas.ts +++ b/src/redux/node/sagas.ts @@ -1,8 +1,14 @@ import { takeLatest, call, put, select, delay } from 'redux-saga/effects'; import { push } from 'connected-react-router'; -import { NODE_ACTIONS } from './constants'; -import { nodeSave, nodeSetSaveErrors, nodeLoadNode, nodeSetLoading } from './actions'; +import { NODE_ACTIONS, EMPTY_NODE } from './constants'; +import { + nodeSave, + nodeSetSaveErrors, + nodeLoadNode, + nodeSetLoading, + nodeSetCurrent, +} from './actions'; import { postNode } from './api'; import { reqWrapper } from '../auth/sagas'; import { flowSetNodes } from '../flow/actions'; @@ -31,10 +37,12 @@ function* onNodeSave({ node }: ReturnType) { return yield put(modalSetShown(false)); } -function* onNodeLoad({ id }: ReturnType) { +function* onNodeLoad({ id, node_type }: ReturnType) { yield put(nodeSetLoading(true)); yield put(nodeSetSaveErrors({})); + if (node_type) yield put(nodeSetCurrent({ ...EMPTY_NODE, type: node_type })); + yield put(push(URLS.NODE_URL(id))); yield delay(1000);