redesign
This commit is contained in:
@@ -1,14 +1,23 @@
|
||||
.comment__action {
|
||||
margin-left: 8px;
|
||||
font-weight: 700;
|
||||
color: #0aa;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
color: #8CD4D4;
|
||||
|
||||
&:hover {
|
||||
color: #06c5c5;
|
||||
color: #0aa;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
+ .comment__controls {
|
||||
&::before {
|
||||
content: '•';
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.comment__avatar_default {
|
||||
border: 1px solid #9cdddb;
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
@import '../comment.vars';
|
||||
|
||||
.comment__avatar {
|
||||
display: inline-block;
|
||||
width: $avatarSize;
|
||||
height: $avatarSize;
|
||||
margin-right: $avatarOffset;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<style>
|
||||
.st6{fill:#8ED0CF}
|
||||
</style>
|
||||
<g>
|
||||
<path d="M4.6 20.5s0 .1 0 0c.9 0 .9-.7 1.9-.7.9 0 .9.8 1.9.8.9 0 .9-.8 1.9-.8s.9.8 1.9.8c.9 0 .9-.8 1.9-.8.9 0 .9.8 1.9.8.9 0 .9-.8 1.9-.8.9 0 .9.8 1.8.8l-.7-3.5c-.2-1.3-.3-2.7-.3-4V9.5c0-3.6-2.9-6.9-6.5-7-3.8-.1-6.9 2.9-6.9 6.7v3.9c0 1.3-.1 2.7-.3 4l-.4 3.4z" fill="#f5f4f4"/>
|
||||
<path d="M8 17.1c.1-1.3.2-2.7.2-4V9.2c0-3.6 1.6-6.5 3.7-6.7-3.6.1-6.5 3-6.5 6.7v3.9c0 1.3-.1 2.7-.3 4l-.5 3.5c.9 0 .9-.8 1.9-.8.7 0 .9.4 1.3.6l.2-3.3z" opacity=".5" fill="#fff"/>
|
||||
<g>
|
||||
<path class="st6" d="M19.3 17c-.2-1.3-.3-2.6-.3-3.9V9.4c0-3.8-2.9-7-6.6-7.3-1.9-.1-3.8.6-5.2 1.9-1.4 1.4-2.3 3.2-2.3 5.2v3.9c0 1.3-.1 2.6-.3 3.9l-.5 3.5c0 .1 0 .2.1.3.1.1.2.2.3.2.6 0 .9-.3 1.2-.5.2-.2.4-.3.7-.3.3 0 .5.1.7.3.3.2.6.5 1.2.5s.9-.3 1.2-.5c.2-.2.4-.3.7-.3s.5.1.7.3c.3.2.6.5 1.2.5s.9-.3 1.2-.5c.2-.2.4-.3.7-.3s.5.1.7.3c.3.2.6.5 1.2.5s.9-.3 1.2-.5c.2-.2.4-.3.7-.3.3 0 .5.1.7.3.3.2.6.5 1.2.5.1 0 .2 0 .3-.1.1-.1.1-.2.1-.3l-.8-3.6zm-.5 2.9c-.3-.2-.6-.5-1.2-.5s-.9.3-1.2.5c-.2.2-.4.3-.7.3-.3 0-.5-.1-.7-.3-.3-.2-.6-.5-1.2-.5s-.9.3-1.2.5c-.2.2-.4.3-.7.3-.3 0-.5-.1-.7-.3-.3-.2-.6-.5-1.2-.5s-.9.3-1.2.5c-.2.2-.4.3-.7.3-.3 0-.5-.1-.7-.3-.3-.2-.6-.5-1.2-.5s-.9.3-1.2.5c.2 0 .1.1 0 .1l.4-2.9c.2-1.3.3-2.7.3-4V9.2c0-1.8.7-3.4 2-4.6 1.3-1.2 2.9-1.8 4.7-1.7 3.3.2 5.9 3.1 5.9 6.5V13c0 1.3.1 2.7.3 4l.4 3c-.1 0-.2-.1-.2-.1z"/>
|
||||
<path class="st6" d="M9.7 7.6c-.6 0-.8.8-.8 1.6s.2 1.6.8 1.6.8-.8.8-1.6-.3-1.6-.8-1.6z"/>
|
||||
<path class="st6" d="M14.4 7.6c-.6 0-.8.8-.8 1.6s.2 1.6.8 1.6.8-.8.8-1.6-.3-1.6-.8-1.6z"/>
|
||||
</g>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" x1="4.1669" y1="14.7127" x2="21.3949" y2="6.6792" gradientTransform="matrix(1 0 0 -1 0 24)">
|
||||
<stop offset="0" stop-color="#fff" stop-opacity=".2"/>
|
||||
<stop offset="1" stop-color="#fff" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,17 @@
|
||||
.comment__control {
|
||||
margin-right: 8px;
|
||||
cursor: pointer;
|
||||
color: #8CD4D4;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #0aa;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
@@ -2,17 +2,11 @@
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
user-select: none;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
|
||||
@media (hover: hover) {
|
||||
font-weight: 700;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
+ .comment__controls_view_admin {
|
||||
&::before {
|
||||
content: '•';
|
||||
margin-left: 8px;
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
.comment__info {
|
||||
margin-bottom: 4px;
|
||||
margin-bottom: 6px;
|
||||
padding-right: 64px;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
.comment__input {
|
||||
padding-left: 32px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.comment__score-sign {
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
.comment__score-value {
|
||||
display: inline-block;
|
||||
min-width: 24px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.comment__score_view_negative {
|
||||
color: #cc0606;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.comment__score_view_positive {
|
||||
color: #259e06;
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
.comment__score {
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
vertical-align: middle;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 0;
|
||||
min-width: 60px;
|
||||
font-size: 0;
|
||||
color: #666;
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
color: #AAA;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
.comment__time {
|
||||
margin-left: 8px;
|
||||
vertical-align: middle;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.comment__vote {
|
||||
display: inline-block;
|
||||
border-top: 9px solid #ccc;
|
||||
border-top: 9px solid #dedede;
|
||||
border-right: 7px solid transparent;
|
||||
border-left: 7px solid transparent;
|
||||
font-size: 0;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
@import '../comment.vars';
|
||||
$step: 24px;
|
||||
|
||||
@for $i from 1 through 5 {
|
||||
.comment_level {
|
||||
&_#{$i} {
|
||||
padding-left: $i * ($avatarSize + $avatarOffset);
|
||||
padding-left: $i * $step;
|
||||
|
||||
&.comment_replying {
|
||||
.comment__input {
|
||||
margin-left: -$i * ($avatarSize + $avatarOffset);
|
||||
margin-left: -$i * $step;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
margin-left: 0;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
@import 'common/variables';
|
||||
|
||||
.comment_pinned {
|
||||
&, &.comment_view_admin {
|
||||
.comment__username {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.comment_replying {
|
||||
border: 3px solid #eee;
|
||||
padding-bottom: 0;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
border: 0;
|
||||
@@ -18,11 +19,19 @@
|
||||
border-left-width: 0;
|
||||
border-right-width: 0;
|
||||
border-bottom-width: 0;
|
||||
padding-left: 0;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
border: 3px solid #eee;
|
||||
padding-left: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.comment__score {
|
||||
top: 12px;
|
||||
right: 8px;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
top: 4px;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,13 +176,6 @@ export default class Comment extends Component {
|
||||
const isAdmin = !guest && store.get('user').admin;
|
||||
const isGuest = guest || !Object.keys(store.get('user')).length;
|
||||
|
||||
const time = new Date(data.time);
|
||||
// TODO: which format for datetime should we choose?
|
||||
// TODO: add smth that will count 'hours ago' (mb this: https://github.com/catamphetamine/javascript-time-ago)
|
||||
// TODO: check out stash's impl;
|
||||
// TODO: don't forget about optional locales, m?
|
||||
// TODO: also date must be a link to the comment
|
||||
const timeStr = `${time.toLocaleDateString([], { month: 'short', day: 'numeric' })}, ${time.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;
|
||||
const o = {
|
||||
...data,
|
||||
text:
|
||||
@@ -197,14 +190,16 @@ export default class Comment extends Component {
|
||||
: data.text
|
||||
)
|
||||
),
|
||||
time: timeStr,
|
||||
time: formatTime(new Date(data.time)),
|
||||
score: {
|
||||
value: Math.abs(score),
|
||||
sign: score > 0 ? '+' : (score < 0 ? '−' : ''),
|
||||
sign: score > 0 ? '+' : (score < 0 ? '−' : null),
|
||||
view: score > 0 ? 'positive' : (score < 0 ? 'negative' : null),
|
||||
},
|
||||
user: {
|
||||
...data.user,
|
||||
picture: data.user.picture.indexOf(API_BASE) === 0 ? `${BASE_URL}${data.user.picture}` : data.user.picture,
|
||||
isDefaultPicture: data.user.picture.indexOf('/avatar/remark.image') > -1, // TODO: rewrite it on backend
|
||||
},
|
||||
};
|
||||
|
||||
@@ -234,116 +229,120 @@ export default class Comment extends Component {
|
||||
<div className={b('comment', props, defaultMods)} id={`remark__comment-${o.id}`}>
|
||||
<div className="comment__body">
|
||||
<div className="comment__info">
|
||||
<img src={o.user.picture} alt="" className="comment__avatar"/>
|
||||
<img
|
||||
className={b('comment__avatar', {}, { default: o.user.isDefaultPicture })}
|
||||
src={o.user.isDefaultPicture ? require('./__avatar/comment__avatar.svg') : o.user.picture}
|
||||
alt=""
|
||||
/>
|
||||
|
||||
<span className="comment__username">{o.user.name}</span>
|
||||
|
||||
{
|
||||
!isGuest && (
|
||||
<span className="comment__score">
|
||||
<span
|
||||
className={b('comment__vote', {}, { type: 'up', selected: scoreIncreased })}
|
||||
onClick={this.increaseScore}
|
||||
>vote up</span>
|
||||
|
||||
<span className="comment__score-sign">{o.score.sign}</span>
|
||||
|
||||
<span className="comment__score-value">{o.score.value}</span>
|
||||
|
||||
<span
|
||||
className={b('comment__vote', {}, { type: 'down', selected: scoreDecreased })}
|
||||
onClick={this.decreaseScore}
|
||||
>vote down</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
<span className="comment__time">{o.time}</span>
|
||||
|
||||
{
|
||||
isAdmin && userBlocked && (
|
||||
<span className="comment__status">blocked</span>
|
||||
<span className="comment__status">Blocked</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
isAdmin && !userBlocked && deleted && (
|
||||
<span className="comment__status">deleted</span>
|
||||
<span className="comment__status">Deleted</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
!mods.disabled && !isGuest && (
|
||||
<span className="comment__controls">
|
||||
!isGuest && (
|
||||
<span className={b('comment__score', {}, { view: o.score.view })}>
|
||||
<span
|
||||
className="comment__action"
|
||||
tabIndex="0"
|
||||
onClick={this.toggleInputVisibility}
|
||||
>reply</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
className={b('comment__vote', {}, { type: 'up', selected: scoreIncreased })}
|
||||
onClick={this.increaseScore}
|
||||
>Vote up</span>
|
||||
|
||||
{
|
||||
isAdmin &&
|
||||
(
|
||||
<span className={b('comment__controls', {}, { view: 'admin' })}>
|
||||
<span className="comment__score-value">
|
||||
{o.score.sign}{o.score.value}
|
||||
</span>
|
||||
|
||||
{
|
||||
!pinned && (
|
||||
<span
|
||||
className="comment__action"
|
||||
tabIndex="0"
|
||||
onClick={this.onPinClick}
|
||||
>pin</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
pinned && (
|
||||
<span
|
||||
className="comment__action"
|
||||
tabIndex="0"
|
||||
onClick={this.onUnpinClick}
|
||||
>unpin</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
userBlocked && (
|
||||
<span
|
||||
className="comment__action"
|
||||
tabIndex="0"
|
||||
onClick={this.onUnblockClick}
|
||||
>unblock</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
!userBlocked && (
|
||||
<span
|
||||
className="comment__action"
|
||||
tabIndex="0"
|
||||
onClick={this.onBlockClick}
|
||||
>block</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
!deleted && (
|
||||
<span
|
||||
className="comment__action"
|
||||
tabIndex="0"
|
||||
onClick={this.onDeleteClick}
|
||||
>delete</span>
|
||||
)
|
||||
}
|
||||
<span
|
||||
className={b('comment__vote', {}, { type: 'down', selected: scoreDecreased })}
|
||||
onClick={this.decreaseScore}
|
||||
>Vote down</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className="comment__text" dangerouslySetInnerHTML={{ __html: o.text }}/>
|
||||
|
||||
<div className="comment__actions">
|
||||
{
|
||||
!mods.disabled && !isGuest && (
|
||||
<span
|
||||
className="comment__action"
|
||||
tabIndex="0"
|
||||
onClick={this.toggleInputVisibility}
|
||||
>{isInputVisible ? 'Cancel' : 'Reply'}</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
isAdmin &&
|
||||
(
|
||||
<span className="comment__controls">
|
||||
{
|
||||
!pinned && (
|
||||
<span
|
||||
className="comment__control"
|
||||
tabIndex="0"
|
||||
onClick={this.onPinClick}
|
||||
>Pin</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
pinned && (
|
||||
<span
|
||||
className="comment__control"
|
||||
tabIndex="0"
|
||||
onClick={this.onUnpinClick}
|
||||
>Unpin</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
userBlocked && (
|
||||
<span
|
||||
className="comment__control"
|
||||
tabIndex="0"
|
||||
onClick={this.onUnblockClick}
|
||||
>Unblock</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
!userBlocked && (
|
||||
<span
|
||||
className="comment__control"
|
||||
tabIndex="0"
|
||||
onClick={this.onBlockClick}
|
||||
>Block</span>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
!deleted && (
|
||||
<span
|
||||
className="comment__control"
|
||||
tabIndex="0"
|
||||
onClick={this.onDeleteClick}
|
||||
>Delete</span>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{
|
||||
@@ -366,3 +365,14 @@ function getTextSnippet(html) {
|
||||
|
||||
return (snippet.length === LENGTH && result.length !== LENGTH) ? `${snippet}...` : snippet;
|
||||
}
|
||||
|
||||
function formatTime(time) {
|
||||
// 'ru-RU' adds a dot as a separator
|
||||
const date = time.toLocaleDateString(['ru-RU'], { day: '2-digit', month: '2-digit', year: '2-digit' });
|
||||
|
||||
// do it manually because Intl API doesn't add leading zeros to hours; idk why
|
||||
const hours = `0${time.getHours()}`.slice(-2);
|
||||
const mins = `0${time.getMinutes()}`.slice(-2);
|
||||
|
||||
return `${date} at ${hours}:${mins}`;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@import 'common/variables';
|
||||
|
||||
.comment {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin-bottom: $offset / 2;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #fcfcfc;
|
||||
font-size: 16px;
|
||||
line-height: 1.2;
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
$avatarSize: 24px;
|
||||
$avatarOffset: 8px;
|
||||
@@ -3,12 +3,19 @@ export { default } from './comment';
|
||||
require('./comment.scss');
|
||||
|
||||
require('./__action/comment__action.scss');
|
||||
|
||||
require('./__avatar/comment__avatar.scss');
|
||||
require('./__avatar/_default/comment__avatar_default.scss');
|
||||
|
||||
require('./__control/comment__control.scss');
|
||||
require('./__controls/comment__controls.scss');
|
||||
require('./__info/comment__info.scss');
|
||||
require('./__input/comment__input.scss');
|
||||
|
||||
require('./__score/comment__score.scss');
|
||||
require('./__score-sign/comment__score-sign.scss');
|
||||
require('./__score/_view/_negative/comment__score_view_negative.scss');
|
||||
require('./__score/_view/_positive/comment__score_view_positive.scss');
|
||||
|
||||
require('./__score-value/comment__score-value.scss');
|
||||
require('./__status/comment__status.scss');
|
||||
require('./__text/comment__text.scss');
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
padding: 8px 12px;
|
||||
font-size: 16px;
|
||||
border: 0;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&:focus {
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
display: block;
|
||||
font-size: 0;
|
||||
border: 3px solid #eee;
|
||||
border-radius: 2px;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
.root__pinned-comment {
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
margin-top: 24px;
|
||||
padding: ($offset / 3) ($offset / 2);
|
||||
border: 2px solid #0aa;
|
||||
border-radius: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
.root {
|
||||
position: relative;
|
||||
font-family: 'PT Sans', Helvetica, Arial, sans-serif;
|
||||
|
||||
::selection {
|
||||
background: #c6efef;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
export { default } from './thread';
|
||||
|
||||
require('./thread.scss');
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
@import 'common/variables';
|
||||
|
||||
.thread {
|
||||
margin-bottom: $offset / 2;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|jpeg|gif)$/,
|
||||
test: /\.(png|jpg|jpeg|gif|svg)$/,
|
||||
use: {
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
|
||||
Reference in New Issue
Block a user