Compare commits
3 Commits
sundas/INF
...
saad/hacka
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa236f96d8 | ||
|
|
ac117c75de | ||
|
|
37ee085253 |
@@ -55,6 +55,8 @@ export const ContentActions = {
|
||||
CHANGE_TOPIC: 'topic_id',
|
||||
CHANGE_TYPE: 'type',
|
||||
VOTE: 'voted',
|
||||
ACCEPT_REVIEW: 'accept_review',
|
||||
REJECT_REVIEW: 'reject_review',
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,14 +8,13 @@ import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Alert } from '@edx/paragon';
|
||||
import { Report } from '@edx/paragon/icons';
|
||||
|
||||
import { AvatarOutlineAndLabelColors } from '../../data/constants';
|
||||
import {
|
||||
selectModerationSettings, selectUserHasModerationPrivileges, selectUserIsGroupTa, selectUserIsStaff,
|
||||
} from '../data/selectors';
|
||||
import { commentShape } from '../post-comments/comments/comment/proptypes';
|
||||
import messages from '../post-comments/messages';
|
||||
import { postShape } from '../posts/post/proptypes';
|
||||
import AlertBar from './AlertBar';
|
||||
import AuthorLabel from './AuthorLabel';
|
||||
|
||||
function AlertBanner({
|
||||
intl,
|
||||
@@ -30,8 +29,6 @@ function AlertBanner({
|
||||
const canSeeLastEditOrClosedAlert = (userHasModerationPrivileges || userIsGroupTa
|
||||
|| userIsGlobalStaff || userIsContentAuthor
|
||||
);
|
||||
const editByLabelColor = AvatarOutlineAndLabelColors[content.editByLabel];
|
||||
const closedByLabelColor = AvatarOutlineAndLabelColors[content.closedByLabel];
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -43,22 +40,40 @@ function AlertBanner({
|
||||
{reasonCodesEnabled && canSeeLastEditOrClosedAlert && (
|
||||
<>
|
||||
{content.lastEdit?.reason && (
|
||||
<AlertBar
|
||||
message={messages.editedBy}
|
||||
author={content.lastEdit.editorUsername}
|
||||
authorLabel={content.editByLabel}
|
||||
labelColor={editByLabelColor && `text-${editByLabelColor}`}
|
||||
reason={content.lastEdit.reason}
|
||||
/>
|
||||
<Alert variant="info" className="px-3 shadow-none mb-1 py-10px bg-light-200">
|
||||
<div className="d-flex align-items-center flex-wrap text-gray-700 font-style">
|
||||
{intl.formatMessage(messages.editedBy)}
|
||||
<span className="ml-1 mr-3">
|
||||
<AuthorLabel author={content.lastEdit.editorUsername} linkToProfile postOrComment />
|
||||
</span>
|
||||
<span
|
||||
className="mx-1.5 font-size-8 font-style text-light-700"
|
||||
style={{ lineHeight: '15px' }}
|
||||
>
|
||||
{intl.formatMessage(messages.fullStop)}
|
||||
</span>
|
||||
{intl.formatMessage(messages.reason)}: {content.lastEdit.reason}
|
||||
</div>
|
||||
</Alert>
|
||||
)}
|
||||
{content.closed && (
|
||||
<AlertBar
|
||||
message={messages.closedBy}
|
||||
author={content.closedBy}
|
||||
authorLabel={content.closedByLabel}
|
||||
labelColor={closedByLabelColor && `text-${closedByLabelColor}`}
|
||||
reason={content.closeReason}
|
||||
/>
|
||||
<Alert variant="info" className="px-3 shadow-none mb-1 py-10px bg-light-200">
|
||||
<div className="d-flex align-items-center flex-wrap text-gray-700 font-style">
|
||||
{intl.formatMessage(messages.closedBy)}
|
||||
<span className="ml-1 ">
|
||||
<AuthorLabel author={content.closedBy} linkToProfile postOrComment />
|
||||
</span>
|
||||
<span
|
||||
className="mx-1.5 font-size-8 font-style text-light-700"
|
||||
style={{ lineHeight: '15px' }}
|
||||
>
|
||||
{intl.formatMessage(messages.fullStop)}
|
||||
</span>
|
||||
|
||||
{content.closeReason && (`${intl.formatMessage(messages.reason)}: ${content.closeReason}`)}
|
||||
|
||||
</div>
|
||||
</Alert>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Alert } from '@edx/paragon';
|
||||
|
||||
import messages from '../post-comments/messages';
|
||||
import AuthorLabel from './AuthorLabel';
|
||||
|
||||
function AlertBar({
|
||||
intl,
|
||||
message,
|
||||
author,
|
||||
authorLabel,
|
||||
labelColor,
|
||||
reason,
|
||||
}) {
|
||||
return (
|
||||
<Alert variant="info" className="px-3 shadow-none mb-1 py-10px bg-light-200">
|
||||
<div className="d-flex align-items-center flex-wrap text-gray-700 font-style">
|
||||
{intl.formatMessage(message)}
|
||||
<span className="ml-1">
|
||||
<AuthorLabel
|
||||
author={author}
|
||||
authorLabel={authorLabel}
|
||||
labelColor={labelColor}
|
||||
linkToProfile
|
||||
postOrComment
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
className="mr-1.5 font-size-8 font-style text-light-700"
|
||||
style={{ lineHeight: '15px' }}
|
||||
>
|
||||
{intl.formatMessage(messages.fullStop)}
|
||||
</span>
|
||||
{reason && (`${intl.formatMessage(messages.reason)}: ${reason}`)}
|
||||
</div>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
AlertBar.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
message: PropTypes.string,
|
||||
author: PropTypes.string,
|
||||
authorLabel: PropTypes.string,
|
||||
labelColor: PropTypes.string,
|
||||
reason: PropTypes.string,
|
||||
};
|
||||
|
||||
AlertBar.defaultProps = {
|
||||
message: '',
|
||||
author: '',
|
||||
authorLabel: '',
|
||||
labelColor: '',
|
||||
reason: '',
|
||||
};
|
||||
|
||||
export default injectIntl(AlertBar);
|
||||
@@ -26,6 +26,16 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Unpin',
|
||||
description: 'Action to unpin a post',
|
||||
},
|
||||
acceptReview: {
|
||||
id: 'discussions.actions.reviewAccept',
|
||||
defaultMessage: 'Accept',
|
||||
description: 'Action to accept content flagged for review',
|
||||
},
|
||||
rejectReview: {
|
||||
id: 'discussions.actions.reviewReject',
|
||||
defaultMessage: 'Decline',
|
||||
description: 'Action to reject content flagged for review',
|
||||
},
|
||||
deleteAction: {
|
||||
id: 'discussions.actions.delete',
|
||||
defaultMessage: 'Delete',
|
||||
|
||||
@@ -151,6 +151,7 @@ export async function updateThread(threadId, {
|
||||
pinned,
|
||||
editReasonCode,
|
||||
closeReasonCode,
|
||||
reviewStatus,
|
||||
} = {}) {
|
||||
const url = `${getThreadsApiUrl()}${threadId}/`;
|
||||
const patchData = snakeCaseObject({
|
||||
@@ -166,6 +167,7 @@ export async function updateThread(threadId, {
|
||||
pinned,
|
||||
editReasonCode,
|
||||
closeReasonCode,
|
||||
reviewStatus,
|
||||
});
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.patch(url, patchData, { headers: { 'Content-Type': 'application/merge-patch+json' } });
|
||||
|
||||
@@ -239,6 +239,7 @@ export function createNewThread({
|
||||
|
||||
export function updateExistingThread(threadId, {
|
||||
flagged, voted, read, topicId, type, title, content, following, closed, pinned, closeReasonCode, editReasonCode,
|
||||
reviewStatus,
|
||||
}) {
|
||||
return async (dispatch) => {
|
||||
try {
|
||||
@@ -256,6 +257,7 @@ export function updateExistingThread(threadId, {
|
||||
pinned,
|
||||
editReasonCode,
|
||||
closeReasonCode,
|
||||
reviewStatus,
|
||||
}));
|
||||
const data = await updateThread(threadId, {
|
||||
flagged,
|
||||
@@ -270,6 +272,7 @@ export function updateExistingThread(threadId, {
|
||||
pinned,
|
||||
editReasonCode,
|
||||
closeReasonCode,
|
||||
reviewStatus,
|
||||
});
|
||||
dispatch(updateThreadSuccess(camelCaseObject(data)));
|
||||
} catch (error) {
|
||||
|
||||
@@ -44,6 +44,7 @@ function Post({
|
||||
const userHasModerationPrivileges = useSelector(selectUserHasModerationPrivileges);
|
||||
const displayPostFooter = post.following || post.voteCount || post.closed
|
||||
|| (post.groupId && userHasModerationPrivileges);
|
||||
const displayReviewContentLabel = post.reviewStatus === "PENDING";
|
||||
|
||||
const handleAbusedFlag = useCallback(() => {
|
||||
if (post.abuseFlagged) {
|
||||
@@ -85,6 +86,8 @@ function Post({
|
||||
[ContentActions.COPY_LINK]: () => { navigator.clipboard.writeText(`${window.location.origin}/${courseId}/posts/${post.id}`); },
|
||||
[ContentActions.PIN]: () => dispatch(updateExistingThread(post.id, { pinned: !post.pinned })),
|
||||
[ContentActions.REPORT]: () => handleAbusedFlag(),
|
||||
[ContentActions.ACCEPT_REVIEW]: () => dispatch(updateExistingThread(post.id, { reviewStatus: "ACCEPTED" })),
|
||||
[ContentActions.REJECT_REVIEW]: () => dispatch(updateExistingThread(post.id, { reviewStatus: "REJECTED" })),
|
||||
}), [
|
||||
showDeleteConfirmation,
|
||||
history,
|
||||
@@ -144,6 +147,8 @@ function Post({
|
||||
/>
|
||||
<AlertBanner content={post} />
|
||||
<PostHeader post={post} />
|
||||
{displayReviewContentLabel && <p style= {{ background: "yellow" }}> This content is under review </p>}
|
||||
|
||||
<div className="d-flex mt-14px text-break font-style text-primary-500">
|
||||
<HTMLLoader htmlNode={post.renderedBody} componentId="post" cssClassName="html-loader" testId={post.id} />
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,8 @@ import { generatePath, useRouteMatch } from 'react-router';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import {
|
||||
CheckCircle, CheckCircleOutline, Delete, Edit, Lock, LockOpen, Pin, Report, Verified, VerifiedOutline,
|
||||
CheckCircle, CheckCircleOutline, Close, Delete, Done,
|
||||
Edit, Lock, LockOpen, Pin, Report, Verified, VerifiedOutline,
|
||||
} from '@edx/paragon/icons';
|
||||
|
||||
import { InsertLink } from '../components/icons';
|
||||
@@ -173,6 +174,20 @@ export const ACTIONS_LIST = [
|
||||
label: messages.deleteAction,
|
||||
conditions: { canDelete: true },
|
||||
},
|
||||
{
|
||||
id: 'accept-review',
|
||||
action: ContentActions.ACCEPT_REVIEW,
|
||||
icon: Done,
|
||||
label: messages.acceptReview,
|
||||
conditions: { reviewStatus: 'PENDING' },
|
||||
},
|
||||
{
|
||||
id: 'reject-review',
|
||||
action: ContentActions.REJECT_REVIEW,
|
||||
icon: Close,
|
||||
label: messages.rejectReview,
|
||||
conditions: { reviewStatus: 'PENDING' },
|
||||
},
|
||||
];
|
||||
|
||||
export function useActions(content) {
|
||||
|
||||
@@ -518,7 +518,3 @@ header {
|
||||
font-size: 18px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.usabilla_live_button_container{
|
||||
right: 0px !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user