diff --git a/src/components/node/NodeRelated/index.tsx b/src/components/node/NodeRelated/index.tsx index eb2af602..118ee233 100644 --- a/src/components/node/NodeRelated/index.tsx +++ b/src/components/node/NodeRelated/index.tsx @@ -2,12 +2,14 @@ import React, { FC, HTMLAttributes } from 'react'; import { range } from 'ramda'; import * as styles from './styles.scss'; import { Group } from '~/components/containers/Group'; +import { INode } from '~/redux/types'; +import { getURL } from '~/utils/dom'; -type IProps = HTMLAttributes & {} +type IProps = HTMLAttributes & { + items: Partial[]; +}; -const NodeRelated: FC = ({ - title, -}) => ( +const NodeRelated: FC = ({ title, items }) => (
@@ -15,9 +17,13 @@ const NodeRelated: FC = ({
- { - range(1, 7).map(el => (
)) - } + {items.map(item => ( +
+ ))}
); diff --git a/src/components/node/NodeRelated/styles.scss b/src/components/node/NodeRelated/styles.scss index dae07ec1..4b7729c5 100644 --- a/src/components/node/NodeRelated/styles.scss +++ b/src/components/node/NodeRelated/styles.scss @@ -7,15 +7,20 @@ .grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(64px, 1fr)); + grid-template-columns: repeat(3, 1fr); grid-template-rows: auto; grid-auto-rows: auto; grid-column-gap: $gap; grid-row-gap: $gap; + + @include tablet { + grid-template-columns: repeat(6, 1fr); + } } .item { - background: darken($content_bg, 2%); + background: darken($content_bg, 2%) 50% 50% no-repeat; + background-size: cover; padding-bottom: 100%; border-radius: $cell_radius; } diff --git a/src/components/node/Tags/index.tsx b/src/components/node/Tags/index.tsx index 89359e35..c3505ccb 100644 --- a/src/components/node/Tags/index.tsx +++ b/src/components/node/Tags/index.tsx @@ -12,6 +12,7 @@ import { TagField } from '~/components/containers/TagField'; import { ITag } from '~/redux/types'; import { Tag } from '~/components/node/Tag'; import uniq from 'ramda/es/uniq'; +import assocPath from 'ramda/es/assocPath'; type IProps = HTMLAttributes & { tags: Partial[]; @@ -65,9 +66,14 @@ export const Tags: FC = ({ tags, is_editable, onTagsChange, ...props }) ); const onSubmit = useCallback(() => { - if (!data.length) return; - onTagsChange(uniq([...tags, ...data]).map(tag => tag.title)); - }, [tags, data, onTagsChange]); + const title = input && input.trim(); + const items = title ? [...data, { title }] : data; + + if (!items.length) return; + setData(items); + setInput(''); + onTagsChange(uniq([...tags, ...items]).map(tag => tag.title)); + }, [tags, data, onTagsChange, input, setInput]); useEffect(() => { setData(data.filter(({ title }) => !tags.some(tag => tag.title.trim() === title.trim()))); diff --git a/src/constants/api.ts b/src/constants/api.ts index 32a7b62a..1a6ee4e0 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -13,6 +13,7 @@ export const API = { GET_NODE: (id: number | string) => `/node/${id}`, COMMENT: (id: INode['id']) => `/node/${id}/comment`, + RELATED: (id: INode['id']) => `/node/${id}/related`, UPDATE_TAGS: (id: INode['id']) => `/node/${id}/tags`, POST_LIKE: (id: INode['id']) => `/node/${id}/like`, POST_STAR: (id: INode['id']) => `/node/${id}/heroic`, diff --git a/src/containers/node/NodeLayout/index.tsx b/src/containers/node/NodeLayout/index.tsx index f45a6dc9..a404e747 100644 --- a/src/containers/node/NodeLayout/index.tsx +++ b/src/containers/node/NodeLayout/index.tsx @@ -42,7 +42,7 @@ const NodeLayoutUnconnected: FC = memo( match: { params: { id }, }, - node: { is_loading, is_loading_comments, comments = [], current: node }, + node: { is_loading, is_loading_comments, comments = [], current: node, related }, user, user: { is_user }, nodeLoadNode, @@ -123,9 +123,9 @@ const NodeLayoutUnconnected: FC = memo( - - - + {related && related.similar && ( + + )}
diff --git a/src/redux/flow/api.ts b/src/redux/flow/api.ts index 17145b59..acdcff66 100644 --- a/src/redux/flow/api.ts +++ b/src/redux/flow/api.ts @@ -35,4 +35,4 @@ export const postCellView = ({ api .post(API.NODE.SET_CELL_VIEW(id), { flow }, configWithToken(access)) .then(resultMiddleware) - .catch(errorMiddleware); + .catch(errorMiddleware); \ No newline at end of file diff --git a/src/redux/node/actions.ts b/src/redux/node/actions.ts index f15cfa68..b97f5c5d 100644 --- a/src/redux/node/actions.ts +++ b/src/redux/node/actions.ts @@ -48,6 +48,11 @@ export const nodeSetComments = (comments: IComment[]) => ({ type: NODE_ACTIONS.SET_COMMENTS, }); +export const nodeSetRelated = (related: INodeState['related']) => ({ + related, + type: NODE_ACTIONS.SET_RELATED, +}); + export const nodeSetCommentData = (id: number, comment: IComment) => ({ id, comment, diff --git a/src/redux/node/api.ts b/src/redux/node/api.ts index 29e586b2..5a98044d 100644 --- a/src/redux/node/api.ts +++ b/src/redux/node/api.ts @@ -2,6 +2,7 @@ import { api, configWithToken, resultMiddleware, errorMiddleware } from '~/utils import { INode, IResultWithStatus, IComment } from '../types'; import { API } from '~/constants/api'; import { nodeUpdateTags, nodeLike, nodeStar } from './actions'; +import { INodeState } from './reducer'; export const postNode = ({ access, @@ -58,12 +59,24 @@ export const getNodeComments = ({ }: { id: number; access: string; -}): Promise> => +}): Promise> => api .get(API.NODE.COMMENT(id), configWithToken(access)) .then(resultMiddleware) .catch(errorMiddleware); +export const getNodeRelated = ({ + id, + access, +}: { + id: number; + access: string; +}): Promise> => + api + .get(API.NODE.RELATED(id), configWithToken(access)) + .then(resultMiddleware) + .catch(errorMiddleware); + export const updateNodeTags = ({ id, tags, diff --git a/src/redux/node/constants.ts b/src/redux/node/constants.ts index e18df061..c246ccd6 100644 --- a/src/redux/node/constants.ts +++ b/src/redux/node/constants.ts @@ -34,6 +34,7 @@ export const NODE_ACTIONS = { POST_COMMENT: `${prefix}POST_COMMENT`, SET_COMMENTS: `${prefix}SET_COMMENTS`, + SET_RELATED: `${prefix}SET_RELATED`, UPDATE_TAGS: `${prefix}UPDATE_TAGS`, SET_TAGS: `${prefix}SET_TAGS`, diff --git a/src/redux/node/handlers.ts b/src/redux/node/handlers.ts index ef7d677c..b09ab335 100644 --- a/src/redux/node/handlers.ts +++ b/src/redux/node/handlers.ts @@ -11,6 +11,7 @@ import { nodeSetTags, nodeSetEditor, nodeSetCoverImage, + nodeSetRelated, } from './actions'; import { INodeState } from './reducer'; @@ -36,6 +37,9 @@ const setSendingComment = ( const setComments = (state: INodeState, { comments }: ReturnType) => assocPath(['comments'], comments, state); +const setRelated = (state: INodeState, { related }: ReturnType) => + assocPath(['related'], related, state); + const setCommentData = ( state: INodeState, { id, comment }: ReturnType @@ -59,6 +63,7 @@ export const NODE_HANDLERS = { [NODE_ACTIONS.SET_CURRENT]: setCurrent, [NODE_ACTIONS.SET_SENDING_COMMENT]: setSendingComment, [NODE_ACTIONS.SET_COMMENTS]: setComments, + [NODE_ACTIONS.SET_RELATED]: setRelated, [NODE_ACTIONS.SET_COMMENT_DATA]: setCommentData, [NODE_ACTIONS.SET_TAGS]: setTags, [NODE_ACTIONS.SET_EDITOR]: setEditor, diff --git a/src/redux/node/reducer.ts b/src/redux/node/reducer.ts index fa15f16e..41e0161d 100644 --- a/src/redux/node/reducer.ts +++ b/src/redux/node/reducer.ts @@ -7,6 +7,10 @@ export type INodeState = Readonly<{ editor: INode; current: INode; comments: IComment[]; + related: { + albums: Record>; + similar: Partial; + }; comment_data: Record; current_cover_image: IFile; @@ -28,6 +32,7 @@ const INITIAL_STATE: INodeState = { current: { ...EMPTY_NODE }, comment_data: { 0: { ...EMPTY_COMMENT } }, comments: [], + related: null, current_cover_image: null, is_loading: false, diff --git a/src/redux/node/sagas.ts b/src/redux/node/sagas.ts index 4e0c577e..dcec5c9e 100644 --- a/src/redux/node/sagas.ts +++ b/src/redux/node/sagas.ts @@ -1,4 +1,4 @@ -import { takeLatest, call, put, select, delay } from 'redux-saga/effects'; +import { takeLatest, call, put, select, delay, all } from 'redux-saga/effects'; import { push } from 'connected-react-router'; import { NODE_ACTIONS, EMPTY_NODE, EMPTY_COMMENT, NODE_EDITOR_DATA } from './constants'; @@ -19,6 +19,7 @@ import { nodeSetEditor, nodeEdit, nodeLike, + nodeSetRelated, } from './actions'; import { postNode, @@ -28,6 +29,7 @@ import { updateNodeTags, postNodeLike, postNodeStar, + getNodeRelated, } from './api'; import { reqWrapper } from '../auth/sagas'; import { flowSetNodes } from '../flow/actions'; @@ -112,11 +114,19 @@ function* onNodeLoad({ id, node_type }: ReturnType) { // todo: load comments const { - data: { comments }, - } = yield call(reqWrapper, getNodeComments, { id }); + comments: { + data: { comments }, + }, + related: { + data: { related }, + }, + } = yield all({ + comments: call(reqWrapper, getNodeComments, { id }), + related: call(reqWrapper, getNodeRelated, { id }), + }); yield put(nodeSetComments(comments || [])); - + yield put(nodeSetRelated(related || [])); yield put(nodeSetLoadingComments(false)); return;