mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 12:56:41 +07:00
several bug fixes
This commit is contained in:
parent
f23b9166e1
commit
11348aa411
13 changed files with 281 additions and 110 deletions
|
@ -228,12 +228,14 @@ const NodeImageSlideBlock: FC<IProps> = ({
|
|||
</div>
|
||||
)}
|
||||
|
||||
<ImageSwitcher
|
||||
total={images.length}
|
||||
current={current}
|
||||
onChange={changeCurrent}
|
||||
loaded={loaded}
|
||||
/>
|
||||
{!is_loading && (
|
||||
<ImageSwitcher
|
||||
total={images.length}
|
||||
current={current}
|
||||
onChange={changeCurrent}
|
||||
loaded={loaded}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={styles.image_container}
|
||||
|
@ -253,7 +255,7 @@ const NodeImageSlideBlock: FC<IProps> = ({
|
|||
is_active: index === current && loaded[index]
|
||||
})}
|
||||
ref={setRef(index)}
|
||||
key={file.id}
|
||||
key={node.updated_at + file.id}
|
||||
>
|
||||
<img
|
||||
className={styles.image}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
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';
|
||||
import React, { FC } from "react";
|
||||
import * as styles from "./styles.scss";
|
||||
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 {
|
||||
is_loading?: boolean;
|
||||
|
@ -17,8 +17,6 @@ const NodeNoComments: FC<IProps> = ({ is_loading = false }) => (
|
|||
<div className={styles.card}>{!is_loading && t(ERRORS.NO_COMMENTS)}</div>
|
||||
<div className={styles.card} />
|
||||
</Group>
|
||||
|
||||
<Filler />
|
||||
</>
|
||||
);
|
||||
|
||||
|
|
|
@ -1,30 +1,34 @@
|
|||
@keyframes fade {
|
||||
0% {
|
||||
opacity: 0.25;
|
||||
// opacity: 0.25;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.1;
|
||||
// opacity: 0.1;
|
||||
}
|
||||
}
|
||||
.wrap {
|
||||
user-select: none;
|
||||
height: 300px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
@include after_shade($node_bg);
|
||||
// @include after_shade($node_bg);
|
||||
|
||||
&:global(.is_loading) {
|
||||
opacity: 1;
|
||||
|
||||
.card {
|
||||
background: $placeholder_bg;
|
||||
animation: fade 0.5s infinite alternate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
opacity: 0.2;
|
||||
opacity: 0.3;
|
||||
border-radius: $radius;
|
||||
height: 96px;
|
||||
background: $comment_bg;
|
||||
background: $placeholder_bg;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -33,7 +37,7 @@
|
|||
color: transparentize(white, 0.5);
|
||||
flex: 0 0 $comment_height;
|
||||
|
||||
@include outer_shadow();
|
||||
// @include outer_shadow();
|
||||
|
||||
&:nth-child(2) {
|
||||
// animation-delay: -300ms !important;
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
import React, { FC, useCallback, useEffect, useRef, useState, memo } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { INode } from '~/redux/types';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { NodePanelInner } from '~/components/node/NodePanelInner';
|
||||
import pick from 'ramda/es/pick';
|
||||
import React, {
|
||||
FC,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
memo
|
||||
} from "react";
|
||||
import * as styles from "./styles.scss";
|
||||
import { INode } from "~/redux/types";
|
||||
import { createPortal } from "react-dom";
|
||||
import { NodePanelInner } from "~/components/node/NodePanelInner";
|
||||
import pick from "ramda/es/pick";
|
||||
|
||||
interface IProps {
|
||||
node: Partial<INode>;
|
||||
|
@ -13,13 +20,25 @@ interface IProps {
|
|||
can_like: boolean;
|
||||
can_star: boolean;
|
||||
|
||||
is_loading?: boolean;
|
||||
|
||||
onEdit: () => void;
|
||||
onLike: () => void;
|
||||
onStar: () => void;
|
||||
}
|
||||
|
||||
const NodePanel: FC<IProps> = memo(
|
||||
({ node, layout, can_edit, can_like, can_star, onEdit, onLike, onStar }) => {
|
||||
({
|
||||
node,
|
||||
layout,
|
||||
can_edit,
|
||||
can_like,
|
||||
can_star,
|
||||
is_loading,
|
||||
onEdit,
|
||||
onLike,
|
||||
onStar
|
||||
}) => {
|
||||
const [stack, setStack] = useState(false);
|
||||
|
||||
const ref = useRef(null);
|
||||
|
@ -35,12 +54,12 @@ const NodePanel: FC<IProps> = memo(
|
|||
|
||||
useEffect(() => {
|
||||
getPlace();
|
||||
window.addEventListener('scroll', getPlace);
|
||||
window.addEventListener('resize', getPlace);
|
||||
window.addEventListener("scroll", getPlace);
|
||||
window.addEventListener("resize", getPlace);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('scroll', getPlace);
|
||||
window.removeEventListener('resize', getPlace);
|
||||
window.removeEventListener("scroll", getPlace);
|
||||
window.removeEventListener("resize", getPlace);
|
||||
};
|
||||
}, [layout]);
|
||||
|
||||
|
@ -57,6 +76,7 @@ const NodePanel: FC<IProps> = memo(
|
|||
can_edit={can_edit}
|
||||
can_like={can_like}
|
||||
can_star={can_star}
|
||||
is_loading={is_loading}
|
||||
/>,
|
||||
document.body
|
||||
)
|
||||
|
@ -69,6 +89,7 @@ const NodePanel: FC<IProps> = memo(
|
|||
can_edit={can_edit}
|
||||
can_like={can_like}
|
||||
can_star={can_star}
|
||||
is_loading={is_loading}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import React, { FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Filler } from '~/components/containers/Filler';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
import { INode } from '~/redux/types';
|
||||
import classNames from 'classnames';
|
||||
import React, { FC } from "react";
|
||||
import * as styles from "./styles.scss";
|
||||
import { Group } from "~/components/containers/Group";
|
||||
import { Filler } from "~/components/containers/Filler";
|
||||
import { Icon } from "~/components/input/Icon";
|
||||
import { INode } from "~/redux/types";
|
||||
import classNames from "classnames";
|
||||
import { Placeholder } from "~/components/placeholders/Placeholder";
|
||||
|
||||
interface IProps {
|
||||
node: Partial<INode>;
|
||||
|
@ -13,6 +14,9 @@ interface IProps {
|
|||
can_edit: boolean;
|
||||
can_like: boolean;
|
||||
can_star: boolean;
|
||||
|
||||
is_loading: boolean;
|
||||
|
||||
onEdit: () => void;
|
||||
onLike: () => void;
|
||||
onStar: () => void;
|
||||
|
@ -21,20 +25,34 @@ interface IProps {
|
|||
const NodePanelInner: FC<IProps> = ({
|
||||
node: { title, user, is_liked, is_heroic },
|
||||
stack,
|
||||
|
||||
can_star,
|
||||
can_edit,
|
||||
can_like,
|
||||
|
||||
is_loading,
|
||||
|
||||
onStar,
|
||||
onEdit,
|
||||
onLike,
|
||||
onLike
|
||||
}) => {
|
||||
return (
|
||||
<div className={classNames(styles.wrap, { stack })}>
|
||||
<div className={styles.content}>
|
||||
<Group horizontal className={styles.panel}>
|
||||
<Filler>
|
||||
<div className={styles.title}>{title || '...'}</div>
|
||||
{user && user.username && <div className={styles.name}>~{user.username}</div>}
|
||||
<div className={styles.title}>
|
||||
{is_loading ? <Placeholder width="40%" /> : title || "..."}
|
||||
</div>
|
||||
{user && user.username && (
|
||||
<div className={styles.name}>
|
||||
{is_loading ? (
|
||||
<Placeholder width="100px" />
|
||||
) : (
|
||||
`~${user.username}`
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Filler>
|
||||
</Group>
|
||||
|
||||
|
|
31
src/components/node/NodeRelated/placeholder.tsx
Normal file
31
src/components/node/NodeRelated/placeholder.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import React, { FC, memo } from "react";
|
||||
import styles from "./styles.scss";
|
||||
import cell_style from "~/components/node/NodeRelatedItem/styles.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 {}
|
||||
|
||||
const NodeRelatedPlaceholder: FC<IProps> = memo(() => {
|
||||
return (
|
||||
<Group className={classNames(styles.wrap, styles.placeholder)}>
|
||||
<div className={styles.title}>
|
||||
<div className={styles.line} />
|
||||
<div className={styles.text}>
|
||||
<Placeholder />
|
||||
</div>
|
||||
<div className={styles.line} />
|
||||
</div>
|
||||
|
||||
<div className={styles.grid}>
|
||||
{range(0, 6).map(el => (
|
||||
<div className={cell_style.item} key={el} />
|
||||
))}
|
||||
</div>
|
||||
</Group>
|
||||
);
|
||||
});
|
||||
|
||||
export { NodeRelatedPlaceholder };
|
|
@ -36,3 +36,15 @@
|
|||
.text {
|
||||
margin: 0 $gap;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
.text {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.grid {
|
||||
div {
|
||||
background: $placeholder_bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
17
src/components/node/NodeTags/placeholder.tsx
Normal file
17
src/components/node/NodeTags/placeholder.tsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import React, { FC, memo } from "react";
|
||||
import { Tags } from "../Tags";
|
||||
import { ITag } from "~/redux/types";
|
||||
|
||||
interface IProps {
|
||||
is_editable?: boolean;
|
||||
tags: ITag[];
|
||||
onChange?: (tags: string[]) => void;
|
||||
}
|
||||
|
||||
const NodeTagsPlaceholder: FC<IProps> = memo(
|
||||
({ is_editable, tags, onChange }) => (
|
||||
<Tags tags={tags} is_editable={is_editable} onTagsChange={onChange} />
|
||||
)
|
||||
);
|
||||
|
||||
export { NodeTagsPlaceholder };
|
|
@ -6,13 +6,12 @@ import React, {
|
|||
useEffect,
|
||||
KeyboardEvent,
|
||||
ChangeEvent,
|
||||
useRef,
|
||||
} from 'react';
|
||||
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';
|
||||
useRef
|
||||
} from "react";
|
||||
import { TagField } from "~/components/containers/TagField";
|
||||
import { ITag } from "~/redux/types";
|
||||
import { Tag } from "~/components/node/Tag";
|
||||
import uniq from "ramda/es/uniq";
|
||||
|
||||
type IProps = HTMLAttributes<HTMLDivElement> & {
|
||||
tags: Partial<ITag>[];
|
||||
|
@ -20,8 +19,13 @@ type IProps = HTMLAttributes<HTMLDivElement> & {
|
|||
onTagsChange?: (tags: string[]) => void;
|
||||
};
|
||||
|
||||
export const Tags: FC<IProps> = ({ tags, is_editable, onTagsChange, ...props }) => {
|
||||
const [input, setInput] = useState('');
|
||||
export const Tags: FC<IProps> = ({
|
||||
tags,
|
||||
is_editable,
|
||||
onTagsChange,
|
||||
...props
|
||||
}) => {
|
||||
const [input, setInput] = useState("");
|
||||
const [data, setData] = useState([]);
|
||||
const timer = useRef(null);
|
||||
|
||||
|
@ -35,17 +39,17 @@ export const Tags: FC<IProps> = ({ tags, is_editable, onTagsChange, ...props })
|
|||
|
||||
const onKeyUp = useCallback(
|
||||
({ key }: KeyboardEvent) => {
|
||||
if (key === 'Backspace' && input === '' && data.length) {
|
||||
if (key === "Backspace" && input === "" && data.length) {
|
||||
setData(data.slice(0, data.length - 1));
|
||||
setInput(data[data.length - 1].title);
|
||||
}
|
||||
|
||||
if (key === 'Enter' || key === ',' || key === 'Comma') {
|
||||
if (key === "Enter" || key === "," || key === "Comma") {
|
||||
setData(
|
||||
uniq([
|
||||
...data,
|
||||
...input
|
||||
.split(',')
|
||||
.split(",")
|
||||
.map((title: string) =>
|
||||
title
|
||||
.trim()
|
||||
|
@ -55,11 +59,11 @@ export const Tags: FC<IProps> = ({ tags, is_editable, onTagsChange, ...props })
|
|||
.filter(el => el.length > 0)
|
||||
.filter(el => !tags.some(tag => tag.title.trim() === el.trim()))
|
||||
.map(title => ({
|
||||
title,
|
||||
})),
|
||||
title
|
||||
}))
|
||||
])
|
||||
);
|
||||
setInput('');
|
||||
setInput("");
|
||||
}
|
||||
},
|
||||
[input, setInput, data, setData]
|
||||
|
@ -71,12 +75,16 @@ export const Tags: FC<IProps> = ({ tags, is_editable, onTagsChange, ...props })
|
|||
|
||||
if (!items.length) return;
|
||||
setData(items);
|
||||
setInput('');
|
||||
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())));
|
||||
setData(
|
||||
data.filter(
|
||||
({ title }) => !tags.some(tag => tag.title.trim() === title.trim())
|
||||
)
|
||||
);
|
||||
}, [tags]);
|
||||
|
||||
return (
|
||||
|
@ -90,7 +98,12 @@ export const Tags: FC<IProps> = ({ tags, is_editable, onTagsChange, ...props })
|
|||
))}
|
||||
|
||||
{is_editable && (
|
||||
<Tag tag={{ title: input }} onInput={onInput} onKeyUp={onKeyUp} onBlur={onSubmit} />
|
||||
<Tag
|
||||
tag={{ title: input }}
|
||||
onInput={onInput}
|
||||
onKeyUp={onKeyUp}
|
||||
onBlur={onSubmit}
|
||||
/>
|
||||
)}
|
||||
</TagField>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.placeholder {
|
||||
height: 1em;
|
||||
width: 120px;
|
||||
background: transparentize(white, 0.95);
|
||||
background: $placeholder_bg;
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
|
|
@ -1,27 +1,36 @@
|
|||
import React, { FC, createElement, useEffect, useCallback, useState, useMemo, memo } from 'react';
|
||||
import { RouteComponentProps } from 'react-router';
|
||||
import { connect } from 'react-redux';
|
||||
import { canEditNode, canLikeNode, canStarNode } from '~/utils/node';
|
||||
import { selectNode } from '~/redux/node/selectors';
|
||||
import { Card } from '~/components/containers/Card';
|
||||
import React, {
|
||||
FC,
|
||||
createElement,
|
||||
useEffect,
|
||||
useCallback,
|
||||
useState,
|
||||
useMemo,
|
||||
memo
|
||||
} from "react";
|
||||
import { RouteComponentProps } from "react-router";
|
||||
import { connect } from "react-redux";
|
||||
import { canEditNode, canLikeNode, canStarNode } from "~/utils/node";
|
||||
import { selectNode } from "~/redux/node/selectors";
|
||||
import { Card } from "~/components/containers/Card";
|
||||
|
||||
import { NodePanel } from '~/components/node/NodePanel';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Padder } from '~/components/containers/Padder';
|
||||
import { NodeNoComments } from '~/components/node/NodeNoComments';
|
||||
import { NodeRelated } from '~/components/node/NodeRelated';
|
||||
import * as styles from './styles.scss';
|
||||
import { NodeComments } from '~/components/node/NodeComments';
|
||||
import { NodeTags } from '~/components/node/NodeTags';
|
||||
import { NODE_COMPONENTS, NODE_INLINES } from '~/redux/node/constants';
|
||||
import * as NODE_ACTIONS from '~/redux/node/actions';
|
||||
import { CommentForm } from '~/components/node/CommentForm';
|
||||
import { selectUser } from '~/redux/auth/selectors';
|
||||
import pick from 'ramda/es/pick';
|
||||
import { NodePanel } from "~/components/node/NodePanel";
|
||||
import { Group } from "~/components/containers/Group";
|
||||
import { Padder } from "~/components/containers/Padder";
|
||||
import { NodeNoComments } from "~/components/node/NodeNoComments";
|
||||
import { NodeRelated } from "~/components/node/NodeRelated";
|
||||
import * as styles from "./styles.scss";
|
||||
import { NodeComments } from "~/components/node/NodeComments";
|
||||
import { NodeTags } from "~/components/node/NodeTags";
|
||||
import { NODE_COMPONENTS, NODE_INLINES } from "~/redux/node/constants";
|
||||
import * as NODE_ACTIONS from "~/redux/node/actions";
|
||||
import { CommentForm } from "~/components/node/CommentForm";
|
||||
import { selectUser } from "~/redux/auth/selectors";
|
||||
import pick from "ramda/es/pick";
|
||||
import { NodeRelatedPlaceholder } from "~/components/node/NodeRelated/placeholder";
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
node: selectNode(state),
|
||||
user: selectUser(state),
|
||||
user: selectUser(state)
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
|
@ -30,7 +39,7 @@ const mapDispatchToProps = {
|
|||
nodeSetCoverImage: NODE_ACTIONS.nodeSetCoverImage,
|
||||
nodeEdit: NODE_ACTIONS.nodeEdit,
|
||||
nodeLike: NODE_ACTIONS.nodeLike,
|
||||
nodeStar: NODE_ACTIONS.nodeStar,
|
||||
nodeStar: NODE_ACTIONS.nodeStar
|
||||
};
|
||||
|
||||
type IProps = ReturnType<typeof mapStateToProps> &
|
||||
|
@ -40,9 +49,15 @@ type IProps = ReturnType<typeof mapStateToProps> &
|
|||
const NodeLayoutUnconnected: FC<IProps> = memo(
|
||||
({
|
||||
match: {
|
||||
params: { id },
|
||||
params: { id }
|
||||
},
|
||||
node: {
|
||||
is_loading,
|
||||
is_loading_comments,
|
||||
comments = [],
|
||||
current: node,
|
||||
related
|
||||
},
|
||||
node: { is_loading, is_loading_comments, comments = [], current: node, related },
|
||||
user,
|
||||
user: { is_user },
|
||||
nodeGotoNode,
|
||||
|
@ -50,8 +65,10 @@ const NodeLayoutUnconnected: FC<IProps> = memo(
|
|||
nodeEdit,
|
||||
nodeLike,
|
||||
nodeStar,
|
||||
nodeSetCoverImage,
|
||||
nodeSetCoverImage
|
||||
}) => {
|
||||
// const is_loading = true;
|
||||
|
||||
const [layout, setLayout] = useState({});
|
||||
|
||||
const updateLayout = useCallback(() => setLayout({}), []);
|
||||
|
@ -86,11 +103,12 @@ const NodeLayoutUnconnected: FC<IProps> = memo(
|
|||
}, [nodeSetCoverImage, node.cover]);
|
||||
|
||||
return (
|
||||
<Card className={styles.node} seamless key={id}>
|
||||
{block && createElement(block, { node, is_loading, updateLayout, layout })}
|
||||
<Card className={styles.node} seamless>
|
||||
{block &&
|
||||
createElement(block, { node, is_loading, updateLayout, layout })}
|
||||
|
||||
<NodePanel
|
||||
node={pick(['title', 'user', 'is_liked', 'is_heroic'], node)}
|
||||
node={pick(["title", "user", "is_liked", "is_heroic"], node)}
|
||||
layout={layout}
|
||||
can_edit={can_edit}
|
||||
can_like={can_like}
|
||||
|
@ -98,6 +116,7 @@ const NodeLayoutUnconnected: FC<IProps> = memo(
|
|||
onEdit={onEdit}
|
||||
onLike={onLike}
|
||||
onStar={onStar}
|
||||
is_loading={is_loading}
|
||||
/>
|
||||
|
||||
<Group>
|
||||
|
@ -106,32 +125,57 @@ const NodeLayoutUnconnected: FC<IProps> = memo(
|
|||
<Group className={styles.comments}>
|
||||
{inline_block && (
|
||||
<div className={styles.inline_block}>
|
||||
{createElement(inline_block, { node, is_loading, updateLayout, layout })}
|
||||
{createElement(inline_block, {
|
||||
node,
|
||||
is_loading,
|
||||
updateLayout,
|
||||
layout
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{is_loading_comments || !comments.length ? (
|
||||
<NodeNoComments is_loading={is_loading_comments} />
|
||||
{is_loading ||
|
||||
is_loading_comments ||
|
||||
(!comments.length && !inline_block) ? (
|
||||
<NodeNoComments
|
||||
is_loading={is_loading_comments || is_loading}
|
||||
/>
|
||||
) : (
|
||||
<NodeComments comments={comments} />
|
||||
)}
|
||||
|
||||
{is_user && <CommentForm id={0} />}
|
||||
{is_user && !is_loading && <CommentForm id={0} />}
|
||||
</Group>
|
||||
|
||||
<div className={styles.panel}>
|
||||
<Group style={{ flex: 1, minWidth: 0 }}>
|
||||
<NodeTags is_editable={is_user} tags={node.tags} onChange={onTagsChange} />
|
||||
{!is_loading && (
|
||||
<NodeTags
|
||||
is_editable={is_user}
|
||||
tags={node.tags}
|
||||
onChange={onTagsChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
{related &&
|
||||
{is_loading && <NodeRelatedPlaceholder />}
|
||||
|
||||
{!is_loading &&
|
||||
related &&
|
||||
related.albums &&
|
||||
Object.keys(related.albums).map(album => (
|
||||
<NodeRelated title={album} items={related.albums[album]} key={album} />
|
||||
<NodeRelated
|
||||
title={album}
|
||||
items={related.albums[album]}
|
||||
key={album}
|
||||
/>
|
||||
))}
|
||||
|
||||
{related && related.similar && related.similar.length > 0 && (
|
||||
<NodeRelated title="ПОХОЖИЕ" items={related.similar} />
|
||||
)}
|
||||
{!is_loading &&
|
||||
related &&
|
||||
related.similar &&
|
||||
related.similar.length > 0 && (
|
||||
<NodeRelated title="ПОХОЖИЕ" items={related.similar} />
|
||||
)}
|
||||
</Group>
|
||||
</div>
|
||||
</Group>
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
.comments {
|
||||
flex: 3 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.panel {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import 'colors';
|
||||
@import "colors";
|
||||
|
||||
$cell: 280px;
|
||||
$gap: 10px;
|
||||
|
@ -13,6 +13,7 @@ $cell_radius: $radius;
|
|||
$panel_radius: $radius;
|
||||
$input_radius: $radius;
|
||||
$dialog_radius: $radius * 2;
|
||||
$placeholder_bg: transparentize(white, 0.96);
|
||||
|
||||
$input_height: 36px;
|
||||
$info_height: 24px;
|
||||
|
@ -30,9 +31,9 @@ $extra_light: 200;
|
|||
|
||||
$upload_button_height: 52px;
|
||||
|
||||
$font: Montserrat, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
|
||||
'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
||||
'Noto Color Emoji';
|
||||
$font: Montserrat, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
|
||||
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
|
||||
$font_48_semibold: $semibold 48px $font;
|
||||
$font_48_bold: $bold 48px $font;
|
||||
|
@ -60,11 +61,14 @@ $font_8_semibold: $semibold 8px $font;
|
|||
$font_cell_title: $bold 30px $font;
|
||||
$font_hero_title: $bold 40px $font;
|
||||
|
||||
$shadow_depth_1: transparentize(black, 0.8) 0 1px, inset transparentize(white, 0.98) 0 1px;
|
||||
$shadow_depth_2: transparentize(black, 0.8) 0 2px, inset transparentize(white, 0.98) 0 1px;
|
||||
$shadow_depth_1: transparentize(black, 0.8) 0 1px,
|
||||
inset transparentize(white, 0.98) 0 1px;
|
||||
$shadow_depth_2: transparentize(black, 0.8) 0 2px,
|
||||
inset transparentize(white, 0.98) 0 1px;
|
||||
|
||||
$comment_shadow: $shadow_depth_2;
|
||||
$node_shadow: transparentize(black, 0.8) 0 2px, transparentize(black, 0.8) 0 2px 4px;
|
||||
$node_shadow: transparentize(black, 0.8) 0 2px,
|
||||
transparentize(black, 0.8) 0 2px 4px;
|
||||
|
||||
$tag_height: 26px;
|
||||
|
||||
|
@ -73,15 +77,18 @@ $input_shadow_error: inset $red 0 0 0 1px;
|
|||
$input_shadow_filled: $input_shadow;
|
||||
|
||||
@mixin outer_shadow() {
|
||||
box-shadow: inset transparentize(white, 0.95) 0 1px, transparentize(black, 0.8) -1px -1px;
|
||||
box-shadow: inset transparentize(white, 0.95) 0 1px,
|
||||
transparentize(black, 0.8) -1px -1px;
|
||||
}
|
||||
|
||||
@mixin inner_shadow() {
|
||||
box-shadow: inset transparentize(white, 0.95) 0 -1px, inset transparentize(black, 0.5) 0 1px;
|
||||
box-shadow: inset transparentize(white, 0.95) 0 -1px,
|
||||
inset transparentize(black, 0.5) 0 1px;
|
||||
}
|
||||
|
||||
@mixin input_shadow() {
|
||||
box-shadow: inset transparentize(white, 0.92) 0 -1px, inset transparentize(black, 0.8) 0 1px;
|
||||
box-shadow: inset transparentize(white, 0.92) 0 -1px,
|
||||
inset transparentize(black, 0.8) 0 1px;
|
||||
}
|
||||
|
||||
@mixin modal_mixin() {
|
||||
|
@ -97,7 +104,7 @@ $input_shadow_filled: $input_shadow;
|
|||
position: $position;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
content: " ";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue