+ {(type === 'response' || type === 'comment') && threadTitle && (
+ <>
+
+
+ {getTypeLabel()} in
+
+ >
+ )}
- {title}
+ {displayTitle}
{isPostPreviewAvailable(previewBody) ? previewBody : intl.formatMessage(messages.postWithoutPreview)}
@@ -121,12 +163,25 @@ const PostLink = ({
{' '}reported
)}
+ {isDeleted && (
+
+ {intl.formatMessage(messages.deletedPost)}
+ {' '}deleted
+
+ )}
{pinned && (
)}
diff --git a/src/discussions/posts/post/messages.js b/src/discussions/posts/post/messages.js
index f095e1fbe..61c49c87a 100644
--- a/src/discussions/posts/post/messages.js
+++ b/src/discussions/posts/post/messages.js
@@ -24,6 +24,25 @@ const messages = defineMessages({
defaultMessage: 'Reported',
description: 'Content reported for staff review',
},
+ deletedBy: {
+ id: 'discussions.post.deletedBy',
+ defaultMessage: 'Deleted by',
+ },
+ deletedPost: {
+ id: 'discussions.post.deletedPost',
+ defaultMessage: 'Deleted',
+ description: 'Badge showing that the post has been deleted',
+ },
+ deletedResponse: {
+ id: 'discussions.post.deletedResponse',
+ defaultMessage: 'Deleted',
+ description: 'Badge showing that the response has been deleted',
+ },
+ deletedComment: {
+ id: 'discussions.post.deletedComment',
+ defaultMessage: 'Deleted',
+ description: 'Badge showing that the comment has been deleted',
+ },
following: {
id: 'discussions.post.following',
defaultMessage: 'Following',
@@ -106,6 +125,14 @@ const messages = defineMessages({
defaultMessage: 'Delete',
description: 'Delete button shown on delete confirmation dialog',
},
+ undeletePostTitle: {
+ id: 'discussions.editor.undelete.post.title',
+ defaultMessage: 'Restore post',
+ },
+ undeletePostDescription: {
+ id: 'discussions.editor.undelete.post.description',
+ defaultMessage: 'Are you sure you want to restore this post?',
+ },
reportPostTitle: {
id: 'discussions.editor.report.post.title',
defaultMessage: 'Report inappropriate content?',
@@ -171,6 +198,11 @@ const messages = defineMessages({
defaultMessage: 'you are not following this post',
description: 'tell screen readers if user is not following a post',
},
+ deleted: {
+ id: 'discussions.post.deleted',
+ defaultMessage: 'Deleted',
+ description: 'Label shown on deleted threads',
+ },
});
export default messages;
diff --git a/src/discussions/utils.js b/src/discussions/utils.js
index fb139f3c6..2b6186377 100644
--- a/src/discussions/utils.js
+++ b/src/discussions/utils.js
@@ -14,6 +14,7 @@ import {
import { getConfig } from '@edx/frontend-platform';
+import { ReactComponent as RestoreFromTrash } from '../assets/undelete.svg';
import { DENIED, LOADED } from '../components/NavigationBar/data/slice';
import {
ContentActions, Routes, ThreadType,
@@ -60,13 +61,17 @@ export function useCommentsPagePath() {
* @returns {boolean}
*/
export function checkPermissions(content, action) {
- if (content.editableFields.includes(action)) {
+ if (content.editableFields && content.editableFields.includes(action)) {
return true;
}
// For delete action we check `content.canDelete`
if (action === ContentActions.DELETE) {
return true;
}
+ // For restore action we check `content.canDelete`
+ if (action === ContentActions.RESTORE) {
+ return content.canDelete;
+ }
return false;
}
@@ -182,7 +187,14 @@ export const ACTIONS_LIST = [
action: ContentActions.DELETE,
icon: Delete,
label: messages.deleteAction,
- conditions: { canDelete: true },
+ conditions: { canDelete: true, isDeleted: false },
+ },
+ {
+ id: 'restore',
+ action: ContentActions.RESTORE,
+ icon: RestoreFromTrash,
+ label: messages.restoreAction,
+ conditions: { canDelete: true, isDeleted: true },
},
];
@@ -203,7 +215,11 @@ export function useActions(contentType, id) {
action,
conditions = null,
}) => checkPermissions(content, action) && checkConditions(content, conditions),
- ), [content]);
+ ).map(action => ({
+ ...action,
+ // For deleted items, disable all actions except 'copy-link' and 'restore'
+ disabled: content.isDeleted && action.id !== 'copy-link' && action.id !== 'restore',
+ })), [content]);
return actions;
}
diff --git a/src/index.scss b/src/index.scss
index fdff64ff1..a43e47598 100755
--- a/src/index.scss
+++ b/src/index.scss
@@ -28,6 +28,19 @@ body,
background-color: var(--pgn-color-card-bg-base) !important;
}
+// New learner message styling
+.new-learner-message {
+ font-style: italic;
+ font-size: 12px;
+ margin-top: 0.25rem;
+ line-height: 1.2;
+
+ @media (max-width: 767.98px) {
+ font-size: 11px;
+ margin-top: 0.1rem;
+ }
+}
+
#post,
#comment,
#reply,
@@ -56,6 +69,22 @@ body,
outline: var(--pgn-color-success-700) solid 2px;
}
+.text-learner-color {
+ color: var(--pgn-color-primary-500);
+}
+
+.outline-learner-color {
+ outline: var(--pgn-color-primary-500) solid 2px;
+}
+
+.text-new-learner-color {
+ color: var(--pgn-color-accent-500);
+}
+
+.outline-new-learner-color {
+ outline: var(--pgn-color-accent-500) solid 2px;
+}
+
.outline-anonymous {
outline: var(--pgn-color-light-400) solid 2px;
}
@@ -558,9 +587,37 @@ code {
.actions-dropdown-item {
padding: 12px 16px;
height: 48px !important;
- min-width: 195px !important
+ min-width: 195px !important;
+ border: none !important;
+ outline: none !important;
+}
+
+.actions-dropdown-item:hover,
+.actions-dropdown-item:focus,
+.actions-dropdown-item:active {
+ border: none !important;
+ outline: none !important;
+ box-shadow: none !important;
+}
+
+.learner-submenu-container {
+ min-width: 280px;
+ max-width: 320px;
+ z-index: 1051;
+ border: 1px solid var(--pgn-color-light-400) !important;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important;
+ outline: none !important;
+}
+
+.learner-submenu-container .actions-dropdown-item {
+ min-width: 280px !important;
+ max-width: 320px !important;
+ white-space: normal;
+ text-align: left;
+ border: none !important;
}
+
.font-xl {
font-size: 18px !important;
line-height: 28px !important;