mirror of
https://github.com/mediacms-io/mediacms.git
synced 2026-06-08 09:52:36 -04:00
Frontent dev env (#247)
* Added frontend development files/environment * More items-categories related removals * Improvements in pages templates (inc. static pages) * Improvements in video player * Added empty home page message + cta * Updates in media, playlist and management pages * Improvements in material icons font loading * Replaced media & playlists links in frontend dev-env * frontend package version update * chnaged frontend dev url port * static files update * Changed default position of theme switcher * enabled frontend docker container
This commit is contained in:
@@ -0,0 +1,455 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { format } from 'timeago.js';
|
||||
import { usePopup } from '../../utils/hooks/';
|
||||
import { PageStore, MediaPageStore } from '../../utils/stores/';
|
||||
import { PageActions, MediaPageActions } from '../../utils/actions/';
|
||||
import { LinksContext, MemberContext, SiteContext } from '../../utils/contexts/';
|
||||
import { PopupMain, UserThumbnail } from '../_shared';
|
||||
|
||||
import './Comments.scss';
|
||||
|
||||
const commentsText = {
|
||||
single: 'comment',
|
||||
uppercaseSingle: 'COMMENT',
|
||||
ucfirstSingle: 'Comment',
|
||||
ucfirstPlural: 'Comments',
|
||||
submitCommentText: 'SUBMIT',
|
||||
disabledCommentsMsg: 'Comments are disabled',
|
||||
};
|
||||
|
||||
function CommentForm(props) {
|
||||
const textareaRef = useRef(null);
|
||||
|
||||
const [value, setValue] = useState('');
|
||||
const [madeChanges, setMadeChanges] = useState(false);
|
||||
const [textareaFocused, setTextareaFocused] = useState(false);
|
||||
const [textareaLineHeight, setTextareaLineHeight] = useState(-1);
|
||||
|
||||
const [loginUrl] = useState(
|
||||
!MemberContext._currentValue.is.anonymous
|
||||
? null
|
||||
: LinksContext._currentValue.signin +
|
||||
'?next=/' +
|
||||
window.location.href.replace(SiteContext._currentValue.url, '').replace(/^\//g, '')
|
||||
);
|
||||
|
||||
function onFocus() {
|
||||
setTextareaFocused(true);
|
||||
}
|
||||
|
||||
function onBlur() {
|
||||
setTextareaFocused(false);
|
||||
}
|
||||
|
||||
function onCommentSubmit() {
|
||||
textareaRef.current.style.height = '';
|
||||
|
||||
const contentHeight = textareaRef.current.scrollHeight;
|
||||
const contentLineHeight =
|
||||
0 < textareaLineHeight ? textareaLineHeight : parseFloat(window.getComputedStyle(textareaRef.current).lineHeight);
|
||||
|
||||
setValue('');
|
||||
setMadeChanges(false);
|
||||
setTextareaLineHeight(contentLineHeight);
|
||||
|
||||
textareaRef.current.style.height =
|
||||
Math.max(20, textareaLineHeight * Math.ceil(contentHeight / contentLineHeight)) + 'px';
|
||||
}
|
||||
|
||||
function onCommentSubmitFail() {
|
||||
setMadeChanges(false);
|
||||
}
|
||||
|
||||
function onChange(event) {
|
||||
textareaRef.current.style.height = '';
|
||||
|
||||
const contentHeight = textareaRef.current.scrollHeight;
|
||||
const contentLineHeight =
|
||||
0 < textareaLineHeight ? textareaLineHeight : parseFloat(window.getComputedStyle(textareaRef.current).lineHeight);
|
||||
|
||||
setValue(textareaRef.current.value);
|
||||
setMadeChanges(true);
|
||||
setTextareaLineHeight(contentLineHeight);
|
||||
|
||||
textareaRef.current.style.height =
|
||||
Math.max(20, textareaLineHeight * Math.ceil(contentHeight / contentLineHeight)) + 'px';
|
||||
}
|
||||
|
||||
function submitComment() {
|
||||
if (!madeChanges) {
|
||||
return;
|
||||
}
|
||||
|
||||
const val = textareaRef.current.value.trim();
|
||||
|
||||
if ('' !== val) {
|
||||
MediaPageActions.submitComment(val);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
MediaPageStore.on('comment_submit', onCommentSubmit);
|
||||
MediaPageStore.on('comment_submit_fail', onCommentSubmitFail);
|
||||
|
||||
return () => {
|
||||
MediaPageStore.removeListener('comment_submit', onCommentSubmit);
|
||||
MediaPageStore.removeListener('comment_submit_fail', onCommentSubmitFail);
|
||||
};
|
||||
});
|
||||
|
||||
return !MemberContext._currentValue.is.anonymous ? (
|
||||
<div className="comments-form">
|
||||
<div className="comments-form-inner">
|
||||
<UserThumbnail />
|
||||
<div className="form">
|
||||
<div className={'form-textarea-wrap' + (textareaFocused ? ' focused' : '')}>
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
className="form-textarea"
|
||||
rows="1"
|
||||
placeholder={'Add a ' + commentsText.single + '...'}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
></textarea>
|
||||
</div>
|
||||
<div className="form-buttons">
|
||||
<button className={'' === value.trim() ? 'disabled' : ''} onClick={submitComment}>
|
||||
{commentsText.submitCommentText}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="comments-form">
|
||||
<div className="comments-form-inner">
|
||||
<UserThumbnail />
|
||||
<div className="form">
|
||||
<a
|
||||
href={loginUrl}
|
||||
rel="noffolow"
|
||||
className="form-textarea-wrap"
|
||||
title={'Add a ' + commentsText.single + '...'}
|
||||
>
|
||||
<span className="form-textarea">{'Add a ' + commentsText.single + '...'}</span>
|
||||
</a>
|
||||
<div className="form-buttons">
|
||||
<a href={loginUrl} rel="noffolow" className="disabled">
|
||||
{commentsText.submitCommentText}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
CommentForm.propTypes = {
|
||||
comment_type: PropTypes.oneOf(['new', 'reply']),
|
||||
media_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
reply_comment_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
};
|
||||
|
||||
CommentForm.defaultProps = {
|
||||
comment_type: 'new',
|
||||
};
|
||||
|
||||
const ENABLED_COMMENTS_READ_MORE = false;
|
||||
|
||||
function CommentActions(props) {
|
||||
const [popupContentRef, PopupContent, PopupTrigger] = usePopup();
|
||||
|
||||
function cancelCommentRemoval() {
|
||||
popupContentRef.current.toggle();
|
||||
}
|
||||
|
||||
function proceedCommentRemoval() {
|
||||
popupContentRef.current.toggle();
|
||||
MediaPageActions.deleteComment(props.comment_id);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="comment-actions">
|
||||
{/*<div className="comment-action like-action"><CircleIconButton><MaterialIcon type="thumb_up" /></CircleIconButton><span className="likes-num">145</span></div>*/}
|
||||
{/*<div className="comment-action dislike-action"><CircleIconButton><MaterialIcon type="thumb_down" /></CircleIconButton><span className="dislikes-num">19</span></div>*/}
|
||||
{/*<div className="comment-action replay-comment"><button>REPLY</button></div>*/}
|
||||
|
||||
{MemberContext._currentValue.can.deleteComment ? (
|
||||
<div className="comment-action remove-comment">
|
||||
<PopupTrigger contentRef={popupContentRef}>
|
||||
<button>DELETE {commentsText.uppercaseSingle}</button>
|
||||
</PopupTrigger>
|
||||
|
||||
<PopupContent contentRef={popupContentRef}>
|
||||
<PopupMain>
|
||||
<div className="popup-message">
|
||||
<span className="popup-message-title">{commentsText.ucfirstSingle} removal</span>
|
||||
<span className="popup-message-main">You're willing to remove {commentsText.single} permanently?</span>
|
||||
</div>
|
||||
<hr />
|
||||
<span className="popup-message-bottom">
|
||||
<button className="button-link cancel-comment-removal" onClick={cancelCommentRemoval}>
|
||||
CANCEL
|
||||
</button>
|
||||
<button className="button-link proceed-comment-removal" onClick={proceedCommentRemoval}>
|
||||
PROCEED
|
||||
</button>
|
||||
</span>
|
||||
</PopupMain>
|
||||
</PopupContent>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Comment(props) {
|
||||
const commentTextRef = useRef(null);
|
||||
const commentTextInnerRef = useRef(null);
|
||||
|
||||
const [viewMoreContent, setViewMoreContent] = useState(!ENABLED_COMMENTS_READ_MORE || false);
|
||||
const [enabledViewMoreContent, setEnabledViewMoreContent] = useState(false);
|
||||
|
||||
function onWindowResize() {
|
||||
const newval = enabledViewMoreContent || commentTextInnerRef.offsetHeight > commentTextRef.offsetHeight;
|
||||
setEnabledViewMoreContent(newval);
|
||||
setViewMoreContent(newval || false);
|
||||
}
|
||||
|
||||
function toggleMore() {
|
||||
setViewMoreContent(!viewMoreContent);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (ENABLED_COMMENTS_READ_MORE) {
|
||||
PageStore.on('window_resize', onWindowResize);
|
||||
setEnabledViewMoreContent(commentTextInnerRef.offsetHeight > commentTextRef.offsetHeight);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (ENABLED_COMMENTS_READ_MORE) {
|
||||
PageStore.removeListener('window_resize', onWindowResize);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="comment">
|
||||
<div className="comment-inner">
|
||||
<a className="comment-author-thumb" href={props.author_link} title={props.author_name}>
|
||||
<img src={props.author_thumb} alt={props.author_name} />
|
||||
</a>
|
||||
<div className="comment-content">
|
||||
<div className="comment-meta">
|
||||
<div className="comment-author">
|
||||
<a href={props.author_link} title={props.author_name}>
|
||||
{props.author_name}
|
||||
</a>
|
||||
</div>
|
||||
<div className="comment-date">{format(new Date(props.publish_date))}</div>
|
||||
</div>
|
||||
<div ref={commentTextRef} className={'comment-text' + (viewMoreContent ? ' show-all' : '')}>
|
||||
<div
|
||||
ref={commentTextInnerRef}
|
||||
className="comment-text-inner"
|
||||
dangerouslySetInnerHTML={{ __html: props.text }}
|
||||
></div>
|
||||
</div>
|
||||
{enabledViewMoreContent ? (
|
||||
<button className="toggle-more" onClick={toggleMore}>
|
||||
{viewMoreContent ? 'Show less' : 'Read more'}
|
||||
</button>
|
||||
) : null}
|
||||
{MemberContext._currentValue.can.deleteComment ? <CommentActions comment_id={props.comment_id} /> : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Comment.propTypes = {
|
||||
comment_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
media_id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
text: PropTypes.string,
|
||||
author_name: PropTypes.string,
|
||||
author_link: PropTypes.string,
|
||||
author_thumb: PropTypes.string,
|
||||
publish_date: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
likes: PropTypes.number,
|
||||
dislikes: PropTypes.number,
|
||||
};
|
||||
|
||||
Comment.defaultProps = {
|
||||
author_name: '',
|
||||
author_link: '#',
|
||||
publish_date: 0,
|
||||
likes: 0,
|
||||
dislikes: 0,
|
||||
};
|
||||
|
||||
function displayCommentsRelatedAlert() {
|
||||
// TODO: Improve this and move it into Media Page code.
|
||||
|
||||
var pageMainEl = document.querySelector('.page-main');
|
||||
var noCommentDiv = pageMainEl.querySelector('.no-comment');
|
||||
|
||||
const postUploadMessage = PageStore.get('config-contents').uploader.postUploadMessage;
|
||||
|
||||
if ('' === postUploadMessage) {
|
||||
if (noCommentDiv && 0 === comm.length) {
|
||||
noCommentDiv.parentNode.removeChild(noCommentDiv);
|
||||
}
|
||||
} else if (0 === comm.length && 'unlisted' === MediaPageStore.get('media-data').state) {
|
||||
if (-1 < LinksContext._currentValue.profile.media.indexOf(MediaPageStore.get('media-data').author_profile)) {
|
||||
if (!noCommentDiv) {
|
||||
const missingCommentariesUnlistedMsgElem = document.createElement('div');
|
||||
|
||||
missingCommentariesUnlistedMsgElem.setAttribute('role', 'alert');
|
||||
missingCommentariesUnlistedMsgElem.setAttribute('class', 'alert info alert-dismissible no-comment');
|
||||
missingCommentariesUnlistedMsgElem.innerHTML =
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' +
|
||||
postUploadMessage;
|
||||
|
||||
if (pageMainEl.firstChild) {
|
||||
pageMainEl.insertBefore(missingCommentariesUnlistedMsgElem, pageMainEl.firstChild);
|
||||
} else {
|
||||
pageMainEl.appendChild(missingCommentariesUnlistedMsgElem);
|
||||
}
|
||||
|
||||
missingCommentariesUnlistedMsgElem.querySelector('button.close').addEventListener('click', function (ev) {
|
||||
missingCommentariesUnlistedMsgElem.setAttribute('class', 'alert info alert-dismissible hiding');
|
||||
setTimeout(function () {
|
||||
missingCommentariesUnlistedMsgElem.parentNode.removeChild(missingCommentariesUnlistedMsgElem);
|
||||
}, 400);
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (noCommentDiv && 0 < comm.length) {
|
||||
noCommentDiv.parentNode.removeChild(noCommentDiv);
|
||||
}
|
||||
}
|
||||
|
||||
const CommentsListHeader = ({ commentsLength }) => {
|
||||
return (
|
||||
<>
|
||||
{!MemberContext._currentValue.can.readComment || MediaPageStore.get('media-data').enable_comments ? null : (
|
||||
<span className="disabled-comments-msg">{commentsText.disabledCommentsMsg}</span>
|
||||
)}
|
||||
|
||||
{MemberContext._currentValue.can.readComment &&
|
||||
(MediaPageStore.get('media-data').enable_comments || MemberContext._currentValue.can.editMedia) ? (
|
||||
<h2>
|
||||
{commentsLength
|
||||
? 1 < commentsLength
|
||||
? commentsLength + ' ' + commentsText.ucfirstPlural
|
||||
: commentsLength + ' ' + commentsText.ucfirstSingle
|
||||
: MediaPageStore.get('media-data').enable_comments
|
||||
? 'No ' + commentsText.single + ' yet'
|
||||
: ''}
|
||||
</h2>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default function CommentsList(props) {
|
||||
const [mediaId, setMediaId] = useState(MediaPageStore.get('media-id'));
|
||||
|
||||
const [comments, setComments] = useState(
|
||||
MemberContext._currentValue.can.readComment ? MediaPageStore.get('media-comments') : []
|
||||
);
|
||||
|
||||
const [displayComments, setDisplayComments] = useState(false);
|
||||
|
||||
function onCommentsLoad() {
|
||||
displayCommentsRelatedAlert();
|
||||
setComments([...MediaPageStore.get('media-comments')]);
|
||||
}
|
||||
|
||||
function onCommentSubmit(commentId) {
|
||||
onCommentsLoad();
|
||||
// FIXME: Without delay creates conflict [ Uncaught Error: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ].
|
||||
setTimeout(() => PageActions.addNotification(commentsText.ucfirstSingle + ' added', 'commentSubmit'), 100);
|
||||
}
|
||||
|
||||
function onCommentSubmitFail() {
|
||||
// FIXME: Without delay creates conflict [ Uncaught Error: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ].
|
||||
setTimeout(
|
||||
() => PageActions.addNotification(commentsText.ucfirstSingle + ' submition failed', 'commentSubmitFail'),
|
||||
100
|
||||
);
|
||||
}
|
||||
|
||||
function onCommentDelete(commentId) {
|
||||
onCommentsLoad();
|
||||
// FIXME: Without delay creates conflict [ Uncaught Error: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ].
|
||||
setTimeout(() => PageActions.addNotification(commentsText.ucfirstSingle + ' removed', 'commentDelete'), 100);
|
||||
}
|
||||
|
||||
function onCommentDeleteFail(commentId) {
|
||||
// FIXME: Without delay creates conflict [ Uncaught Error: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ].
|
||||
setTimeout(
|
||||
() => PageActions.addNotification(commentsText.ucfirstSingle + ' removal failed', 'commentDeleteFail'),
|
||||
100
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setDisplayComments(
|
||||
comments.length &&
|
||||
MemberContext._currentValue.can.readComment &&
|
||||
(MediaPageStore.get('media-data').enable_comments || MemberContext._currentValue.can.editMedia)
|
||||
);
|
||||
}, [comments]);
|
||||
|
||||
useEffect(() => {
|
||||
MediaPageStore.on('comments_load', onCommentsLoad);
|
||||
MediaPageStore.on('comment_submit', onCommentSubmit);
|
||||
MediaPageStore.on('comment_submit_fail', onCommentSubmitFail);
|
||||
MediaPageStore.on('comment_delete', onCommentDelete);
|
||||
MediaPageStore.on('comment_delete_fail', onCommentDeleteFail);
|
||||
|
||||
return () => {
|
||||
MediaPageStore.removeListener('comments_load', onCommentsLoad);
|
||||
MediaPageStore.removeListener('comment_submit', onCommentSubmit);
|
||||
MediaPageStore.removeListener('comment_submit_fail', onCommentSubmitFail);
|
||||
MediaPageStore.removeListener('comment_delete', onCommentDelete);
|
||||
MediaPageStore.removeListener('comment_delete_fail', onCommentDeleteFail);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="comments-list">
|
||||
<div className="comments-list-inner">
|
||||
<CommentsListHeader commentsLength={comments.length} />
|
||||
|
||||
{MediaPageStore.get('media-data').enable_comments ? <CommentForm media_id={mediaId} /> : null}
|
||||
|
||||
{displayComments
|
||||
? comments.map((c) => {
|
||||
return (
|
||||
<Comment
|
||||
key={c.uid}
|
||||
comment_id={c.uid}
|
||||
media_id={mediaId}
|
||||
text={c.text}
|
||||
author_name={c.author_name}
|
||||
author_link={c.author_profile}
|
||||
author_thumb={SiteContext._currentValue.url + '/' + c.author_thumbnail_url.replace(/^\//g, '')}
|
||||
publish_date={c.add_date}
|
||||
likes={0}
|
||||
dislikes={0}
|
||||
/>
|
||||
);
|
||||
})
|
||||
: null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+511
@@ -0,0 +1,511 @@
|
||||
@import '../../../css/includes/_variables.scss';
|
||||
|
||||
.comments-form-inner {
|
||||
.form {
|
||||
.form-textarea-wrap {
|
||||
border-color: var(--comments-textarea-wrapper-border-color);
|
||||
|
||||
&:after {
|
||||
background-color: var(--comments-textarea-wrapper-after-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
color: var(--comments-textarea-text-color);
|
||||
|
||||
&:placeholder {
|
||||
color: var(--comments-textarea-text-placeholder-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comments-list-inner {
|
||||
border-color: var(--comments-list-inner-border-color);
|
||||
}
|
||||
|
||||
.comment-author {
|
||||
color: var(--comment-author-text-color);
|
||||
|
||||
a {
|
||||
color: var(--comment-author-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
.comment-date {
|
||||
color: var(--comment-date-text-color);
|
||||
text-decoration-color: var(--comment-date-text-color);
|
||||
|
||||
a {
|
||||
color: var(--comment-date-text-color);
|
||||
text-decoration-color: var(--comment-date-text-color);
|
||||
|
||||
&:hover {
|
||||
color: var(--comment-date-hover-text-color);
|
||||
text-decoration-color: var(--comment-date-hover-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comment-text {
|
||||
color: var(--comment-text-color);
|
||||
}
|
||||
|
||||
.comment-actions {
|
||||
button {
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.circle-icon-button {
|
||||
background-color: var(--body-bg-color);
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: var(--comment-actions-material-icon-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
.likes-num,
|
||||
.dislikes-num {
|
||||
color: var(--comment-actions-likes-num-text-color);
|
||||
}
|
||||
|
||||
.reply-comment {
|
||||
> button {
|
||||
color: var(--comment-actions-reply-button-text-color);
|
||||
|
||||
background: none;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: var(--comment-actions-reply-button-hover-text-color);
|
||||
|
||||
.material-icons {
|
||||
color: var(--comment-actions-reply-button-hover-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.remove-comment {
|
||||
.popup-message-bottom {
|
||||
button {
|
||||
&.cancel-comment-removal {
|
||||
color: var(--comment-actions-cancel-removal-button-text-color);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: var(--comment-actions-cancel-removal-button-hover-text-color);
|
||||
|
||||
.material-icons {
|
||||
color: var(--comment-actions-cancel-removal-button-hover-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comments-form {
|
||||
position: relative;
|
||||
margin: 0 0 1.5rem;
|
||||
}
|
||||
|
||||
.comments-form-inner {
|
||||
min-height: 40px;
|
||||
|
||||
.thumbnail {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.form {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-left: 56px;
|
||||
|
||||
.form-textarea-wrap {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 0 0 0.3em;
|
||||
border-style: solid;
|
||||
border-width: 0 0 1px;
|
||||
|
||||
&:after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
&.focused {
|
||||
&:after {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
position: relative;
|
||||
resize: none;
|
||||
display: block;
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
outline: 0;
|
||||
border-style: solid;
|
||||
border: 0;
|
||||
min-height: 20px;
|
||||
height: auto;
|
||||
text-decoration: none;
|
||||
overflow-y: hidden;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-word;
|
||||
vertical-align: baseline;
|
||||
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
background-color: transparent;
|
||||
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
line-height: 21px;
|
||||
|
||||
&:placeholder {
|
||||
font-size: 15px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
a.form-textarea-wrap {
|
||||
&:focus {
|
||||
outline: 1px dotted rgba(#0a0a0a, 0.5);
|
||||
}
|
||||
|
||||
text-decoration: none;
|
||||
|
||||
.form-textarea {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.form-buttons {
|
||||
margin-top: 8px;
|
||||
text-align: right;
|
||||
|
||||
a,
|
||||
button {
|
||||
display: inline-block;
|
||||
padding: 12px 16px 10px;
|
||||
margin-left: 8px;
|
||||
line-height: 1;
|
||||
font-weight: 400;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
border: 0;
|
||||
border-radius: 1px;
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comments-list {
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.comments-list-inner {
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
|
||||
padding-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
|
||||
@media screen and (min-width: 640px) {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1008px) {
|
||||
padding-top: 24px;
|
||||
margin-bottom: 0;
|
||||
border-bottom: 0;
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
}
|
||||
|
||||
h2 {
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
margin: 0 2rem 1.5rem 0;
|
||||
}
|
||||
|
||||
.disabled-comments-msg {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.ratings-container + .comments-list .comments-list-inner {
|
||||
margin-top: -16px;
|
||||
border-top-width: 0;
|
||||
}
|
||||
|
||||
.comment-replies {
|
||||
}
|
||||
|
||||
.comment-replies-inner {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.comment {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.comment-inner {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.comment-author-thumb {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
border-radius: 9999px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.comment-content {
|
||||
position: relative;
|
||||
width: auto;
|
||||
margin: 0 0 0 56px;
|
||||
display: inline-block;
|
||||
|
||||
.toggle-more {
|
||||
padding: 0;
|
||||
margin: 8px 0 0 0;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
overflow-wrap: break-word;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.comment-meta {
|
||||
display: block;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.comment-author {
|
||||
display: inline-block;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 18px;
|
||||
margin: 0 4px 2px 0;
|
||||
}
|
||||
|
||||
.comment-date {
|
||||
display: inline-block;
|
||||
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
|
||||
a {
|
||||
text-transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
.comment-text {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
overflow-wrap: break-word;
|
||||
word-break: break-word;
|
||||
white-space: pre-wrap;
|
||||
overflow: hidden;
|
||||
|
||||
max-height: (5 * 20px);
|
||||
|
||||
@media screen and (min-width: 1008px) {
|
||||
max-height: (4 * 20px);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1216px) {
|
||||
max-height: (3 * 20px);
|
||||
}
|
||||
|
||||
&.show-all {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
p:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.comment-text-inner {
|
||||
}
|
||||
}
|
||||
|
||||
.comment-actions {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
color: #909090;
|
||||
|
||||
.circle-icon-button {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
color: #909090;
|
||||
font-size: 16px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.comment-action {
|
||||
display: inline-block;
|
||||
|
||||
~ * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.likes-num,
|
||||
.dislikes-num {
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.reply-comment,
|
||||
.remove-comment {
|
||||
> button {
|
||||
padding: 8px 16px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
line-height: 15px;
|
||||
border: 0;
|
||||
border-radius: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.reply-comment {
|
||||
> button {
|
||||
}
|
||||
}
|
||||
|
||||
.remove-comment {
|
||||
position: relative;
|
||||
width: auto;
|
||||
// float:right;
|
||||
margin-top: 0.5rem;
|
||||
|
||||
> button {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.popup {
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 0;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.popup-message-bottom {
|
||||
button {
|
||||
position: relative;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
|
||||
&.cancel-comment-removal,
|
||||
&.proceed-comment-removal {
|
||||
background-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
&.proceed-comment-removal {
|
||||
float: right;
|
||||
}
|
||||
|
||||
&.cancel-comment-removal {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.comment-replies {
|
||||
}
|
||||
Reference in New Issue
Block a user