mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 04:46:40 +07:00
node no comments
This commit is contained in:
parent
b4d7bd2c8a
commit
96bdbb0e04
11 changed files with 103 additions and 61 deletions
|
@ -1,16 +1,25 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { Comment } from '~/components/node/Comment';
|
|
||||||
import * as styles from './styles.scss';
|
import * as styles from './styles.scss';
|
||||||
import { Group } from '~/components/containers/Group';
|
import { Group } from '~/components/containers/Group';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { Filler } from '~/components/containers/Filler';
|
||||||
|
import { ERRORS } from '~/constants/errors';
|
||||||
|
import { t } from '~/utils/trans';
|
||||||
|
|
||||||
interface IProps {}
|
interface IProps {
|
||||||
|
is_loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
const NodeNoComments: FC<IProps> = () => (
|
const NodeNoComments: FC<IProps> = ({ is_loading = false }) => (
|
||||||
<Group className={styles.wrap}>
|
<>
|
||||||
<Comment is_empty is_loading={false} style={{ height: 94 }} />
|
<Group className={classNames(styles.wrap, { is_loading })}>
|
||||||
<Comment is_empty is_loading={false} style={{ height: 104 }} />
|
<div className={styles.card} />
|
||||||
<Comment is_empty is_loading={false} style={{ height: 100 }} />
|
<div className={styles.card}>{!is_loading && t(ERRORS.NO_COMMENTS)}</div>
|
||||||
</Group>
|
<div className={styles.card} />
|
||||||
|
</Group>
|
||||||
|
|
||||||
|
<Filler />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
export { NodeNoComments };
|
export { NodeNoComments };
|
||||||
|
|
|
@ -1,6 +1,43 @@
|
||||||
|
@keyframes fade {
|
||||||
|
0% {
|
||||||
|
opacity: 0.25;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
.wrap {
|
.wrap {
|
||||||
height: 300px;
|
height: 300px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
@include after_shade($node_bg);
|
@include after_shade($node_bg);
|
||||||
|
|
||||||
|
&:global(.is_loading) {
|
||||||
|
.card {
|
||||||
|
animation: fade 0.5s infinite alternate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
opacity: 0.2;
|
||||||
|
border-radius: $radius;
|
||||||
|
height: 96px;
|
||||||
|
background: $comment_bg;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font: $font_18_semibold;
|
||||||
|
color: transparentize(white, 0.5);
|
||||||
|
@include outer_shadow();
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
// animation-delay: -300ms !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
// animation-delay: -600ms !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,9 @@ export const ERRORS = {
|
||||||
NOT_AN_EMAIL: 'Not_An_Email',
|
NOT_AN_EMAIL: 'Not_An_Email',
|
||||||
TOO_SHIRT: 'Is_Too_Shirt',
|
TOO_SHIRT: 'Is_Too_Shirt',
|
||||||
EMPTY_RESPONSE: 'Empty_Response',
|
EMPTY_RESPONSE: 'Empty_Response',
|
||||||
|
NO_COMMENTS: 'No_Comments',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ERROR_LITERAL = {
|
||||||
|
[ERRORS.NO_COMMENTS]: 'Комментариев пока нет',
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,53 +13,7 @@ import { ImageSwitcher } from '~/components/node/ImageSwitcher';
|
||||||
|
|
||||||
interface IProps {}
|
interface IProps {}
|
||||||
|
|
||||||
const ImageExample: FC<IProps> = () => (
|
const ImageExample: FC<IProps> = () => <Card className={styles.node} seamless></Card>;
|
||||||
<Card className={styles.node} seamless>
|
|
||||||
<ImageSwitcher total={5} current={2} onChange={console.log} />
|
|
||||||
|
|
||||||
<div className={styles.image_container}>
|
|
||||||
<img
|
|
||||||
className={styles.image}
|
|
||||||
src="http://37.192.131.144/full/attached/2019/08/e4fb2a1d0a2e20d499aaa1f5f83a7115.jpg"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<NodePanel />
|
|
||||||
|
|
||||||
<Group>
|
|
||||||
<Padder>
|
|
||||||
<Group horizontal className={styles.content}>
|
|
||||||
<Group className={styles.comments}>
|
|
||||||
<NodeNoComments />
|
|
||||||
|
|
||||||
{range(1, 6).map(el => (
|
|
||||||
<Comment key={el} />
|
|
||||||
))}
|
|
||||||
</Group>
|
|
||||||
|
|
||||||
<div className={styles.panel}>
|
|
||||||
<Group style={{ flex: 1 }}>
|
|
||||||
<Tags
|
|
||||||
tags={[
|
|
||||||
{ title: 'Избранный', feature: 'red' },
|
|
||||||
{ title: 'Плейлист', feature: 'green' },
|
|
||||||
{ title: 'Просто' },
|
|
||||||
{ title: '+ фото', feature: 'black' },
|
|
||||||
{ title: '+ с музыкой', feature: 'black' },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<NodeRelated title="First album" />
|
|
||||||
|
|
||||||
<NodeRelated title="Second album" />
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
</Group>
|
|
||||||
</Padder>
|
|
||||||
</Group>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
|
|
||||||
export { ImageExample };
|
export { ImageExample };
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ const NodeLayoutUnconnected: FC<IProps> = ({
|
||||||
params: { id },
|
params: { id },
|
||||||
},
|
},
|
||||||
is_loading,
|
is_loading,
|
||||||
|
is_loading_comments,
|
||||||
|
comments = [],
|
||||||
current: node,
|
current: node,
|
||||||
nodeLoadNode,
|
nodeLoadNode,
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -50,8 +52,11 @@ const NodeLayoutUnconnected: FC<IProps> = ({
|
||||||
<Padder>
|
<Padder>
|
||||||
<Group horizontal className={styles.content}>
|
<Group horizontal className={styles.content}>
|
||||||
<Group className={styles.comments}>
|
<Group className={styles.comments}>
|
||||||
<NodeNoComments />
|
{is_loading_comments || !comments.length || true ? (
|
||||||
<NodeComments />
|
<NodeNoComments is_loading={is_loading_comments} />
|
||||||
|
) : (
|
||||||
|
<NodeComments />
|
||||||
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<div className={styles.panel}>
|
<div className={styles.panel}>
|
||||||
|
|
|
@ -23,6 +23,11 @@ export const nodeSetLoading = (is_loading: INodeState['is_loading']) => ({
|
||||||
type: NODE_ACTIONS.SET_LOADING,
|
type: NODE_ACTIONS.SET_LOADING,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const nodeSetLoadingComments = (is_loading_comments: INodeState['is_loading_comments']) => ({
|
||||||
|
is_loading_comments,
|
||||||
|
type: NODE_ACTIONS.SET_LOADING_COMMENTS,
|
||||||
|
});
|
||||||
|
|
||||||
export const nodeSetCurrent = (current: INodeState['current']) => ({
|
export const nodeSetCurrent = (current: INodeState['current']) => ({
|
||||||
current,
|
current,
|
||||||
type: NODE_ACTIONS.SET_CURRENT,
|
type: NODE_ACTIONS.SET_CURRENT,
|
||||||
|
|
|
@ -10,6 +10,7 @@ export const NODE_ACTIONS = {
|
||||||
|
|
||||||
SET_SAVE_ERRORS: `${prefix}SET_SAVE_ERRORS`,
|
SET_SAVE_ERRORS: `${prefix}SET_SAVE_ERRORS`,
|
||||||
SET_LOADING: `${prefix}SET_LOADING`,
|
SET_LOADING: `${prefix}SET_LOADING`,
|
||||||
|
SET_LOADING_COMMENTS: `${prefix}SET_LOADING_COMMENTS`,
|
||||||
SET_CURRENT: `${prefix}SET_CURRENT`,
|
SET_CURRENT: `${prefix}SET_CURRENT`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import assocPath from 'ramda/es/assocPath';
|
import assocPath from 'ramda/es/assocPath';
|
||||||
import { NODE_ACTIONS } from './constants';
|
import { NODE_ACTIONS } from './constants';
|
||||||
import { nodeSetSaveErrors, nodeSetLoading, nodeSetCurrent } from './actions';
|
import {
|
||||||
|
nodeSetSaveErrors,
|
||||||
|
nodeSetLoading,
|
||||||
|
nodeSetCurrent,
|
||||||
|
nodeSetLoadingComments,
|
||||||
|
} from './actions';
|
||||||
import { INodeState } from './reducer';
|
import { INodeState } from './reducer';
|
||||||
|
|
||||||
const setSaveErrors = (state: INodeState, { errors }: ReturnType<typeof nodeSetSaveErrors>) =>
|
const setSaveErrors = (state: INodeState, { errors }: ReturnType<typeof nodeSetSaveErrors>) =>
|
||||||
|
@ -9,11 +14,17 @@ const setSaveErrors = (state: INodeState, { errors }: ReturnType<typeof nodeSetS
|
||||||
const setLoading = (state: INodeState, { is_loading }: ReturnType<typeof nodeSetLoading>) =>
|
const setLoading = (state: INodeState, { is_loading }: ReturnType<typeof nodeSetLoading>) =>
|
||||||
assocPath(['is_loading'], is_loading, state);
|
assocPath(['is_loading'], is_loading, state);
|
||||||
|
|
||||||
|
const setLoadingComments = (
|
||||||
|
state: INodeState,
|
||||||
|
{ is_loading_comments }: ReturnType<typeof nodeSetLoadingComments>
|
||||||
|
) => assocPath(['is_loading_comments'], is_loading_comments, state);
|
||||||
|
|
||||||
const setCurrent = (state: INodeState, { current }: ReturnType<typeof nodeSetCurrent>) =>
|
const setCurrent = (state: INodeState, { current }: ReturnType<typeof nodeSetCurrent>) =>
|
||||||
assocPath(['current'], current, state);
|
assocPath(['current'], current, state);
|
||||||
|
|
||||||
export const NODE_HANDLERS = {
|
export const NODE_HANDLERS = {
|
||||||
[NODE_ACTIONS.SAVE]: setSaveErrors,
|
[NODE_ACTIONS.SAVE]: setSaveErrors,
|
||||||
[NODE_ACTIONS.SET_LOADING]: setLoading,
|
[NODE_ACTIONS.SET_LOADING]: setLoading,
|
||||||
|
[NODE_ACTIONS.SET_LOADING_COMMENTS]: setLoadingComments,
|
||||||
[NODE_ACTIONS.SET_CURRENT]: setCurrent,
|
[NODE_ACTIONS.SET_CURRENT]: setCurrent,
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,12 +4,15 @@ import { EMPTY_NODE } from './constants';
|
||||||
import { NODE_HANDLERS } from './handlers';
|
import { NODE_HANDLERS } from './handlers';
|
||||||
|
|
||||||
export type INodeState = Readonly<{
|
export type INodeState = Readonly<{
|
||||||
is_loading: boolean;
|
|
||||||
editor: INode;
|
editor: INode;
|
||||||
current: Partial<INode>;
|
current: INode;
|
||||||
comments: IComment[];
|
comments: IComment[];
|
||||||
|
|
||||||
error: string;
|
error: string;
|
||||||
errors: Record<string, string>;
|
errors: Record<string, string>;
|
||||||
|
|
||||||
|
is_loading: boolean;
|
||||||
|
is_loading_comments: boolean;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const INITIAL_STATE: INodeState = {
|
const INITIAL_STATE: INodeState = {
|
||||||
|
@ -19,9 +22,10 @@ const INITIAL_STATE: INodeState = {
|
||||||
blocks: [],
|
blocks: [],
|
||||||
files: [],
|
files: [],
|
||||||
},
|
},
|
||||||
current: {},
|
current: { ...EMPTY_NODE },
|
||||||
comments: [],
|
comments: [],
|
||||||
is_loading: false,
|
is_loading: false,
|
||||||
|
is_loading_comments: false,
|
||||||
error: null,
|
error: null,
|
||||||
errors: {},
|
errors: {},
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
nodeLoadNode,
|
nodeLoadNode,
|
||||||
nodeSetLoading,
|
nodeSetLoading,
|
||||||
nodeSetCurrent,
|
nodeSetCurrent,
|
||||||
|
nodeSetLoadingComments,
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import { postNode, getNode } from './api';
|
import { postNode, getNode } from './api';
|
||||||
import { reqWrapper } from '../auth/sagas';
|
import { reqWrapper } from '../auth/sagas';
|
||||||
|
@ -39,6 +40,7 @@ function* onNodeSave({ node }: ReturnType<typeof nodeSave>) {
|
||||||
|
|
||||||
function* onNodeLoad({ id, node_type }: ReturnType<typeof nodeLoadNode>) {
|
function* onNodeLoad({ id, node_type }: ReturnType<typeof nodeLoadNode>) {
|
||||||
yield put(nodeSetLoading(true));
|
yield put(nodeSetLoading(true));
|
||||||
|
yield put(nodeSetLoadingComments(true));
|
||||||
yield put(nodeSetSaveErrors({}));
|
yield put(nodeSetSaveErrors({}));
|
||||||
|
|
||||||
if (node_type) yield put(nodeSetCurrent({ ...EMPTY_NODE, type: node_type }));
|
if (node_type) yield put(nodeSetCurrent({ ...EMPTY_NODE, type: node_type }));
|
||||||
|
@ -58,6 +60,10 @@ function* onNodeLoad({ id, node_type }: ReturnType<typeof nodeLoadNode>) {
|
||||||
yield put(nodeSetSaveErrors({}));
|
yield put(nodeSetSaveErrors({}));
|
||||||
yield put(nodeSetCurrent(node));
|
yield put(nodeSetCurrent(node));
|
||||||
|
|
||||||
|
// todo: load comments
|
||||||
|
yield delay(500);
|
||||||
|
yield put(nodeSetLoadingComments(false));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
src/utils/trans.ts
Normal file
5
src/utils/trans.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { ERRORS, ERROR_LITERAL } from '~/constants/errors';
|
||||||
|
import { ValueOf } from '~/redux/types';
|
||||||
|
|
||||||
|
export const t = (string: ValueOf<typeof ERRORS>): ValueOf<typeof ERROR_LITERAL> =>
|
||||||
|
ERROR_LITERAL[string] || string;
|
Loading…
Add table
Add a link
Reference in a new issue