diff --git a/src/components/moderation-modal.js b/src/components/moderation-modal.js index 62b961e..2d20677 100644 --- a/src/components/moderation-modal.js +++ b/src/components/moderation-modal.js @@ -21,7 +21,7 @@ export default function ModerationModal({ ref={ref} id="moderation-reason" name="moderationReason" - rows="2" + rows="4" /> diff --git a/src/components/preprint-card.js b/src/components/preprint-card.js index a3a61ba..1f4a3b1 100644 --- a/src/components/preprint-card.js +++ b/src/components/preprint-card.js @@ -269,6 +269,7 @@ export default function PreprintCard({
)} @@ -131,6 +133,8 @@ const ReviewReader = React.memo(function ReviewReader({ }); ReviewReader.propTypes = { + user: PropTypes.object, + role: PropTypes.object, preview: PropTypes.bool, identifier: PropTypes.string.isRequired, // DOI or arXivID onHighlighedRoleIdsChange: PropTypes.func, @@ -152,7 +156,6 @@ ReviewReader.propTypes = { ).isRequired, nRequests: PropTypes.number, defaultHighlightedRoleIds: PropTypes.arrayOf(PropTypes.string), - canModerate: PropTypes.bool, isModerationInProgress: PropTypes.bool, onModerate: PropTypes.func }; diff --git a/src/components/shell-content.js b/src/components/shell-content.js index dea4362..c521207 100644 --- a/src/components/shell-content.js +++ b/src/components/shell-content.js @@ -214,7 +214,7 @@ function ShellContentRead({ user, preprint, actions, fetchActionsProgress }) { const location = useLocation(); const history = useHistory(); - const [moderation, setModeration] = useState(null); + const [moderatedReviewId, setModeratedReviewId] = useState(null); const [post, postProgress, resetPostState] = usePostAction(); const [role, fetchRoleProgress] = useRole(user && user.defaultRole); @@ -273,11 +273,12 @@ function ShellContentRead({ user, preprint, actions, fetchActionsProgress }) { {!fetchActionsProgress.isActive && ( { + onModerate={reportedActionId => { resetPostState(); - setModeration({ type, object }); + setModeratedReviewId(reportedActionId); }} onHighlighedRoleIdsChange={roleIds => { if (process.env.IS_EXTENSION) { @@ -310,29 +311,26 @@ function ShellContentRead({ user, preprint, actions, fetchActionsProgress }) { /> )} - {!!moderation && ( + {!!moderatedReviewId && ( { post( cleanup({ - '@type': - moderation.type === 'role' - ? 'ModerateRoleAction' - : 'ModerateRapidPREReviewAction', + '@type': 'ReportRapidPREreviewAction', agent: user.defaultRole, actionStatus: 'CompletedActionStatus', - object: moderation.object, + object: moderatedReviewId, moderationReason }), - () => { - setModeration(null); + body => { + setModeratedReviewId(null); } ); }} onCancel={() => { - setModeration(null); + setModeratedReviewId(null); }} /> )} diff --git a/src/components/text-answers.js b/src/components/text-answers.js index bf5ab90..20e581c 100644 --- a/src/components/text-answers.js +++ b/src/components/text-answers.js @@ -3,13 +3,22 @@ import PropTypes from 'prop-types'; import { MenuItem } from '@reach/menu-button'; import Value from './value'; import RoleBadge from './role-badge'; +import { getId, arrayify } from '../utils/jsonld'; +import { getTextAnswers } from '../utils/stats'; export default function TextAnswers({ - answers, - canModerate, + user, + role, + actions, isModerationInProgress, onModerate }) { + const answers = getTextAnswers(actions); + + const isLoggedIn = !!user; + + console.log(actions); + return (
@@ -18,36 +27,37 @@ export default function TextAnswers({
{question}
- {answers.map(({ actionId, roleId, text }) => ( -
-
- - {!!canModerate && ( - { - onModerate('role', roleId); - }} - > - Report Author - - )} - {!!canModerate && ( - { - onModerate('review', actionId); - }} - > - Report Author’s Review - - )} - -
+ {answers.map(({ actionId, roleId, text }) => { + const action = actions.find(action => getId(action) === actionId); + return ( +
+
+ + {isLoggedIn && ( + + action['@type'] === + 'ReportRapidPREreviewAction' && + getId(action.agent) === getId(role) + ) + } + onSelect={() => { + onModerate(actionId); + }} + > + Report Author’s Review + + )} + +
- {text} -
- ))} + {text} + + ); + })}
))} @@ -56,18 +66,25 @@ export default function TextAnswers({ } TextAnswers.propTypes = { - answers: PropTypes.arrayOf( + user: PropTypes.object, + role: PropTypes.object, + actions: PropTypes.arrayOf( PropTypes.shape({ - questionId: PropTypes.string.isRequired, - question: PropTypes.string.isRequired, - answers: PropTypes.arrayOf( + '@type': PropTypes.oneOf(['RapidPREreviewAction']).isRequired, + actionStatus: PropTypes.oneOf(['CompletedActionStatus']).isRequired, + agent: PropTypes.string.isRequired, + moderationAction: PropTypes.arrayOf( PropTypes.shape({ - roleId: PropTypes.string.isRequired, - text: PropTypes.string.isRequired + '@type': PropTypes.oneOf([ + // !! `ModerateRapidPREreviewAction` cannot be present reviews with it must be excluded upstream + 'ReportRapidPREreviewAction', + 'IgnoreReportRapidPREreviewAction' + ]).isRequired }) ) }) ).isRequired, + canBan: PropTypes.bool, canModerate: PropTypes.bool, isModerationInProgress: PropTypes.bool, onModerate: PropTypes.func diff --git a/src/components/text-answers.stories.js b/src/components/text-answers.stories.js index 9a3ced5..630577a 100644 --- a/src/components/text-answers.stories.js +++ b/src/components/text-answers.stories.js @@ -1,24 +1,53 @@ import React from 'react'; import faker from 'faker'; +import sample from 'lodash/sample'; +import { BrowserRouter as Router } from 'react-router-dom'; import TextAnswers from './text-answers'; import { QUESTIONS } from '../constants'; +import { StoresProvider } from '../contexts/store-context'; +import { RoleStore } from '../stores/user-stores'; export default { title: 'TextAnswers' }; -export function Random() { - const roleIds = ['role:role1', 'role:role2']; +const roleStore = new RoleStore(); - const answers = QUESTIONS.filter(({ type }) => { - return type === 'Question'; - }).map(({ question, identifier }) => { - return { - questionId: `question:${identifier}`, - question, - answers: roleIds.map(roleId => { - return { roleId, text: faker.lorem.paragraph() }; - }) - }; - }); +export function Random() { + const actions = ['role:roleId1', 'role:roleId2', 'role:roleId3'].map( + roleId => { + return { + '@type': 'RapidPREreviewAction', + agent: roleId, + actionStatus: 'CompletedActionStatus', + object: 'doi:doi', + resultReview: { + '@type': 'RapidPREreview', + about: [ + { + '@type': 'OutbreakScienceEntity', + name: sample(['Influenza', 'Dengue', 'Zika']) + } + ], + reviewAnswer: QUESTIONS.map(question => { + return { + '@type': + question.type === 'YesNoQuestion' ? 'YesNoAnswer' : 'Answer', + parentItem: `question:${question.identifier}`, + text: + question.type === 'YesNoQuestion' + ? sample(['yes', 'no', 'n.a.', 'unsure']) + : faker.lorem.paragraph() + }; + }) + } + }; + } + ); - return ; + return ( + + + + + + ); } diff --git a/src/db/db.js b/src/db/db.js index 7232dbc..683f739 100644 --- a/src/db/db.js +++ b/src/db/db.js @@ -461,6 +461,7 @@ export default class DB { } // potential action: we merge all distincts + // TODO handle `moderationAction` merged.potentialAction = uniqBy( arrayify(merged.potentialAction).concat( arrayify(doc.potentialAction) @@ -486,6 +487,7 @@ export default class DB { }); } + // TODO handle `moderationAction` if ( !merged.potentialAction.some( _action => getId(_action) === getId(action) diff --git a/src/hooks/api-hooks.js b/src/hooks/api-hooks.js index d3936bd..fbb015c 100644 --- a/src/hooks/api-hooks.js +++ b/src/hooks/api-hooks.js @@ -89,7 +89,7 @@ export function usePostAction() { if (body['@type'] === 'UpdateUserAction') { setUser(body.result); - } else if (body['@type'] === 'ModerateRapidPREReviewAction') { + } else if (body['@type'] === 'ModerateRapidPREreviewAction') { preprintsSearchResultsStore.reset(); } diff --git a/src/middlewares/cache.js b/src/middlewares/cache.js index 77f6909..75b3647 100644 --- a/src/middlewares/cache.js +++ b/src/middlewares/cache.js @@ -191,10 +191,12 @@ export function invalidate() { break; } - case 'ModerateRapidPREReviewAction': + case 'ReportRapidPREreviewAction': + case 'IgnoreReportRapidPREreviewAction': + case 'ModerateRapidPREreviewAction': case 'RequestForRapidPREreviewAction': case 'RapidPREreviewAction': { - if (action['@type'] === 'ModerateRapidPREReviewAction') { + if (action['@type'] === 'ModerateRapidPREreviewAction') { action = action.result; } diff --git a/src/stores/preprint-stores.js b/src/stores/preprint-stores.js index 0c15e70..a771e90 100644 --- a/src/stores/preprint-stores.js +++ b/src/stores/preprint-stores.js @@ -76,7 +76,11 @@ export class PreprintsWithActionsStore extends EventEmitter { } upsertAction(action) { - if (action['@type'] === 'ModerateRapidPREReviewAction') { + if ( + action['@type'] === 'ModerateRapidPREreviewAction' || + action['@type'] === 'ReportRapidPREreviewAction' || + action['@type'] === 'IgnoreReportRapidPREreviewAction' + ) { action = action.result; } diff --git a/src/utils/preprints.js b/src/utils/preprints.js index b388bd4..30c44ea 100644 --- a/src/utils/preprints.js +++ b/src/utils/preprints.js @@ -35,6 +35,11 @@ export function dehydrateAction(action) { ); break; + case 'moderationAction': + // TODO + // only keep ModerateRapidPREreviewAction ? + break; + default: compacted[key] = action[key]; break;