From 25ec9b3a60ed416c3dfd38aad90db3c41b4a1d4b Mon Sep 17 00:00:00 2001 From: pepermao Date: Tue, 2 Jul 2024 21:53:44 +0200 Subject: [PATCH 1/5] Added reviewTaskType field in reviewTask schema Deleted lookup aggregation files Rename selectedClaim dispatch state to selectedTarget Enabled source reviews drawer visualization Refactored kanban components Fixed BaseList race condition Refactored reviewTask list all function to allow multiple types of reviewTask --- src/components/ClaimReview/ClaimReviewDrawer.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/ClaimReview/ClaimReviewDrawer.tsx b/src/components/ClaimReview/ClaimReviewDrawer.tsx index 0c40fc364..6c8f77a81 100644 --- a/src/components/ClaimReview/ClaimReviewDrawer.tsx +++ b/src/components/ClaimReview/ClaimReviewDrawer.tsx @@ -19,7 +19,6 @@ import { useAtom } from "jotai"; import { currentNameSpace } from "../../atoms/namespace"; import colors from "../../styles/colors"; import { generateReviewContentPath } from "../../utils/GetReviewContentHref"; -import { ReviewTaskTypeEnum } from "../../machines/reviewTask/enums"; const ClaimReviewDrawer = () => { const [isLoading, setIsLoading] = useState(true); From cabfbed6cc38fbd188a2400b2d0773f4574d44bf Mon Sep 17 00:00:00 2001 From: pepermao Date: Tue, 16 Jul 2024 18:26:47 +0200 Subject: [PATCH 2/5] Enable reviewers to update the report under a feature flag Reviewers can now add sources and suggestions Created floating menu component to encapsulate floating components in one Enable users to view the report preview under a feature flag Users can now see the report preview in real-time Created editor readonly logic --- public/locales/en/claimReviewForm.json | 4 +- public/locales/pt/claimReviewForm.json | 4 +- server/claim/claim.controller.ts | 30 ++++ server/feature-flag/feature-flag.service.ts | 16 ++ server/review-task/review-task.controller.ts | 6 + server/source/source.controller.ts | 53 ++----- server/source/source.module.ts | 2 + .../ClaimReview/ClaimReviewDrawer.tsx | 1 + .../ClaimReview/ClaimReviewHeader.tsx | 8 - .../ClaimReview/ClaimReviewView.tsx | 70 +++++---- .../Comment/CommentContainer.tsx | 71 +++------ .../Components/AffixPreviewButton.tsx | 46 ++++++ .../Components/ClaimReviewEditor.tsx | 1 - .../Collaborative/Components/FloatingMenu.tsx | 56 +++++++ .../Components/FloatingMenuContent.tsx | 39 +++++ .../Components/FloatingMenuIcons.tsx | 68 ++++++++ .../LinkToolBar/FloatingLinkToolbar.tsx | 108 ++++--------- .../Collaborative/VisualEditor.style.tsx | 5 + src/components/Collaborative/VisualEditor.tsx | 6 +- .../Collaborative/VisualEditorProvider.tsx | 31 +++- .../SentenceReport/SentenceReportCard.tsx | 5 +- .../SentenceReport/SentenceReportPreview.tsx | 32 ++++ .../SentenceReportPreviewView.tsx | 147 ++++++++++++++++++ .../SentenceReport/SentenceReportSummary.tsx | 1 + .../SentenceReport/SentenceReportView.tsx | 11 +- .../reviewTask/ReviewTaskMachineProvider.tsx | 7 + src/machines/reviewTask/actions.ts | 10 +- src/machines/reviewTask/enums.ts | 1 + src/machines/reviewTask/getNextEvent.ts | 5 +- src/machines/reviewTask/getNextForm.ts | 18 +-- src/machines/reviewTask/machineWorkflow.ts | 43 +++-- src/machines/reviewTask/reviewTaskMachine.ts | 2 +- src/pages/claim-page.tsx | 31 ++-- src/pages/claim-review.tsx | 39 +++-- src/pages/kanban-page.tsx | 34 ++-- src/pages/source-review.tsx | 39 +++-- src/store/actions.ts | 20 +++ src/store/store.ts | 28 +--- src/store/types.ts | 8 +- 39 files changed, 758 insertions(+), 348 deletions(-) create mode 100644 src/components/Collaborative/Components/AffixPreviewButton.tsx create mode 100644 src/components/Collaborative/Components/FloatingMenu.tsx create mode 100644 src/components/Collaborative/Components/FloatingMenuContent.tsx create mode 100644 src/components/Collaborative/Components/FloatingMenuIcons.tsx create mode 100644 src/components/SentenceReport/SentenceReportPreview.tsx create mode 100644 src/components/SentenceReport/SentenceReportPreviewView.tsx diff --git a/public/locales/en/claimReviewForm.json b/public/locales/en/claimReviewForm.json index 7c3f72aa2..7c27a3c07 100644 --- a/public/locales/en/claimReviewForm.json +++ b/public/locales/en/claimReviewForm.json @@ -54,5 +54,7 @@ "groupLabel": "Group verification requests", "groupPlaceholder": "Select verification requests", "isSensitiveLabel": "Sensitve content", - "isSensitive": "This verification request contains sensitve content" + "isSensitive": "This verification request contains sensitve content", + "viewPreview": "View preview", + "hidePreview": "Hide preview" } diff --git a/public/locales/pt/claimReviewForm.json b/public/locales/pt/claimReviewForm.json index 9f992f60d..6a75e21ec 100644 --- a/public/locales/pt/claimReviewForm.json +++ b/public/locales/pt/claimReviewForm.json @@ -54,5 +54,7 @@ "groupLabel": "Agrupar denúncias", "groupPlaceholder": "Selecione denúncias", "isSensitiveLabel": "Conteúdo confidencial", - "isSensitive": "Esta denúncia contém conteúdo confidencial" + "isSensitive": "Esta denúncia contém conteúdo confidencial", + "viewPreview": "Visualizar pré-visualização", + "hidePreview": "Ocultar pré-visualização" } diff --git a/server/claim/claim.controller.ts b/server/claim/claim.controller.ts index cc7e402ce..86905a8d6 100644 --- a/server/claim/claim.controller.ts +++ b/server/claim/claim.controller.ts @@ -359,6 +359,10 @@ export class ClaimController { this.featureFlagService.isEnableEditorAnnotations(); const enableAddEditorSourcesWithoutSelecting = this.featureFlagService.isEnableAddEditorSourcesWithoutSelecting(); + const enableReviewersUpdateReport = + this.featureFlagService.isEnableReviewersUpdateReport(); + const enableViewReportPreview = + this.featureFlagService.isEnableViewReportPreview(); hideDescriptions[TargetModel.Claim] = await this.historyService.getDescriptionForHide( @@ -390,6 +394,8 @@ export class ClaimController { enableEditorAnnotations, enableCopilotChatBot, enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, + enableViewReportPreview, websocketUrl: this.configService.get("websocketUrl"), nameSpace: req.params.namespace, }) @@ -579,6 +585,10 @@ export class ClaimController { this.featureFlagService.isEnableEditorAnnotations(); const enableAddEditorSourcesWithoutSelecting = this.featureFlagService.isEnableAddEditorSourcesWithoutSelecting(); + const enableReviewersUpdateReport = + this.featureFlagService.isEnableReviewersUpdateReport(); + const enableViewReportPreview = + this.featureFlagService.isEnableViewReportPreview(); this.redirectBasedOnPersonality(res, claim, namespace); @@ -593,6 +603,8 @@ export class ClaimController { enableEditorAnnotations, enableCopilotChatBot, enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, + enableViewReportPreview, websocketUrl: this.configService.get("websocketUrl"), nameSpace: namespace, }) @@ -616,6 +628,10 @@ export class ClaimController { this.featureFlagService.isEnableEditorAnnotations(); const enableAddEditorSourcesWithoutSelecting = this.featureFlagService.isEnableAddEditorSourcesWithoutSelecting(); + const enableReviewersUpdateReport = + this.featureFlagService.isEnableReviewersUpdateReport(); + const enableViewReportPreview = + this.featureFlagService.isEnableViewReportPreview(); const claim = await this.claimService.getByClaimSlug( claimSlug, @@ -633,6 +649,8 @@ export class ClaimController { enableEditorAnnotations, enableCopilotChatBot: enableCopilotChatBot, enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, + enableViewReportPreview, websocketUrl: this.configService.get("websocketUrl"), nameSpace: namespace, }) @@ -659,6 +677,10 @@ export class ClaimController { this.featureFlagService.isEnableEditorAnnotations(); const enableAddEditorSourcesWithoutSelecting = this.featureFlagService.isEnableAddEditorSourcesWithoutSelecting(); + const enableReviewersUpdateReport = + this.featureFlagService.isEnableReviewersUpdateReport(); + const enableViewReportPreview = + this.featureFlagService.isEnableViewReportPreview(); const personality = await this.personalityService.getClaimsByPersonalitySlug( @@ -692,6 +714,8 @@ export class ClaimController { enableEditorAnnotations, enableCopilotChatBot, enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, + enableViewReportPreview, websocketUrl: this.configService.get("websocketUrl"), hideDescriptions, nameSpace: namespace, @@ -725,6 +749,10 @@ export class ClaimController { this.featureFlagService.isEnableEditorAnnotations(); const enableAddEditorSourcesWithoutSelecting = this.featureFlagService.isEnableAddEditorSourcesWithoutSelecting(); + const enableReviewersUpdateReport = + this.featureFlagService.isEnableReviewersUpdateReport(); + const enableViewReportPreview = + this.featureFlagService.isEnableViewReportPreview(); const claim = await this.claimService.getByPersonalityIdAndClaimSlug( personality._id, @@ -743,6 +771,8 @@ export class ClaimController { enableEditorAnnotations, enableCopilotChatBot: enableCopilotChatBot, enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, + enableViewReportPreview, websocketUrl: this.configService.get("websocketUrl"), nameSpace: namespace, }) diff --git a/server/feature-flag/feature-flag.service.ts b/server/feature-flag/feature-flag.service.ts index bf0d1939d..b864062ad 100644 --- a/server/feature-flag/feature-flag.service.ts +++ b/server/feature-flag/feature-flag.service.ts @@ -40,4 +40,20 @@ export class FeatureFlagService { ) : false; } + + isEnableReviewersUpdateReport() { + const config = this.configService.get("feature_flag"); + + return config + ? this.unleash.isEnabled("enable_reviewers_update_report") + : false; + } + + isEnableViewReportPreview() { + const config = this.configService.get("feature_flag"); + + return config + ? this.unleash.isEnabled("enable_view_report_preview") + : false; + } } diff --git a/server/review-task/review-task.controller.ts b/server/review-task/review-task.controller.ts index 29a2a2a6f..ce4ca1437 100644 --- a/server/review-task/review-task.controller.ts +++ b/server/review-task/review-task.controller.ts @@ -171,6 +171,10 @@ export class ReviewTaskController { this.featureFlagService.isEnableEditorAnnotations(); const enableAddEditorSourcesWithoutSelecting = this.featureFlagService.isEnableAddEditorSourcesWithoutSelecting(); + const enableReviewersUpdateReport = + this.featureFlagService.isEnableReviewersUpdateReport(); + const enableViewReportPreview = + this.featureFlagService.isEnableViewReportPreview(); await this.viewService.getNextServer().render( req, @@ -182,6 +186,8 @@ export class ReviewTaskController { enableEditorAnnotations, enableCopilotChatBot, enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, + enableViewReportPreview, websocketUrl: this.configService.get("websocketUrl"), nameSpace: req.params.namespace, }) diff --git a/server/source/source.controller.ts b/server/source/source.controller.ts index 1c37f9ed4..f0c0b722a 100644 --- a/server/source/source.controller.ts +++ b/server/source/source.controller.ts @@ -26,6 +26,7 @@ import { TargetModel } from "../history/schema/history.schema"; import { HistoryService } from "../history/history.service"; import { ReviewTaskService } from "../review-task/review-task.service"; import { ClaimReviewService } from "../claim-review/claim-review.service"; +import { FeatureFlagService } from "../feature-flag/feature-flag.service"; @Controller(":namespace?") export class SourceController { @@ -38,6 +39,7 @@ export class SourceController { private claimReviewService: ClaimReviewService, private reviewTaskService: ReviewTaskService, private historyService: HistoryService, + private featureFlagService: FeatureFlagService, @Optional() private readonly unleash: UnleashService ) {} @@ -163,12 +165,18 @@ export class SourceController { source.data_hash ); - const enableCollaborativeEditor = this.isEnableCollaborativeEditor(); - const enableCopilotChatBot = this.isEnableCopilotChatBot(); - const enableEditorAnnotations = this.isEnableEditorAnnotations(); + const enableCollaborativeEditor = + this.featureFlagService.isEnableCollaborativeEditor(); + const enableCopilotChatBot = + this.featureFlagService.isEnableCopilotChatBot(); + const enableEditorAnnotations = + this.featureFlagService.isEnableEditorAnnotations(); const enableAddEditorSourcesWithoutSelecting = - this.isEnableAddEditorSourcesWithoutSelecting(); - + this.featureFlagService.isEnableAddEditorSourcesWithoutSelecting(); + const enableReviewersUpdateReport = + this.featureFlagService.isEnableReviewersUpdateReport(); + const enableViewReportPreview = + this.featureFlagService.isEnableViewReportPreview(); const hideDescriptions = {}; hideDescriptions[TargetModel.Source] = @@ -199,42 +207,11 @@ export class SourceController { enableEditorAnnotations, enableCopilotChatBot, enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, + enableViewReportPreview, websocketUrl: this.configService.get("websocketUrl"), nameSpace: req.params.namespace, }) ); } - - //TODO: Create service to get feature flags config - private isEnableCollaborativeEditor() { - const config = this.configService.get("feature_flag"); - - return config - ? this.unleash.isEnabled("enable_collaborative_editor") - : false; - } - - private isEnableCopilotChatBot() { - const config = this.configService.get("feature_flag"); - - return config ? this.unleash.isEnabled("copilot_chat_bot") : false; - } - - private isEnableEditorAnnotations() { - const config = this.configService.get("feature_flag"); - - return config - ? this.unleash.isEnabled("enable_editor_annotations") - : false; - } - - private isEnableAddEditorSourcesWithoutSelecting() { - const config = this.configService.get("feature_flag"); - - return config - ? this.unleash.isEnabled( - "enable_add_editor_sources_without_selecting" - ) - : false; - } } diff --git a/server/source/source.module.ts b/server/source/source.module.ts index 4bd568448..fea38bcac 100644 --- a/server/source/source.module.ts +++ b/server/source/source.module.ts @@ -9,6 +9,7 @@ import { CaptchaModule } from "../captcha/captcha.module"; import { HistoryModule } from "../history/history.module"; import { ClaimReviewModule } from "../claim-review/claim-review.module"; import { ReviewTaskModule } from "../review-task/review-task.module"; +import { FeatureFlagModule } from "../feature-flag/feature-flag.module"; const SourceModel = MongooseModule.forFeature([ { @@ -26,6 +27,7 @@ const SourceModel = MongooseModule.forFeature([ HistoryModule, forwardRef(() => ClaimReviewModule), ReviewTaskModule, + FeatureFlagModule, ], providers: [SourceService], exports: [SourceService], diff --git a/src/components/ClaimReview/ClaimReviewDrawer.tsx b/src/components/ClaimReview/ClaimReviewDrawer.tsx index 6c8f77a81..0c40fc364 100644 --- a/src/components/ClaimReview/ClaimReviewDrawer.tsx +++ b/src/components/ClaimReview/ClaimReviewDrawer.tsx @@ -19,6 +19,7 @@ import { useAtom } from "jotai"; import { currentNameSpace } from "../../atoms/namespace"; import colors from "../../styles/colors"; import { generateReviewContentPath } from "../../utils/GetReviewContentHref"; +import { ReviewTaskTypeEnum } from "../../machines/reviewTask/enums"; const ClaimReviewDrawer = () => { const [isLoading, setIsLoading] = useState(true); diff --git a/src/components/ClaimReview/ClaimReviewHeader.tsx b/src/components/ClaimReview/ClaimReviewHeader.tsx index 1811f52af..0afeeb360 100644 --- a/src/components/ClaimReview/ClaimReviewHeader.tsx +++ b/src/components/ClaimReview/ClaimReviewHeader.tsx @@ -5,7 +5,6 @@ import React, { useContext } from "react"; import { ReviewTaskMachineContext } from "../../machines/reviewTask/ReviewTaskMachineProvider"; import { ClassificationEnum, TargetModel } from "../../types/enums"; import { publishedSelector } from "../../machines/reviewTask/selectors"; -import { useAppSelector } from "../../store/store"; import colors from "../../styles/colors"; import SentenceReportCard from "../SentenceReport/SentenceReportCard"; import TopicInput from "./TopicInput"; @@ -32,13 +31,6 @@ const ClaimReviewHeader = ({ componentStyle, target, }: ClaimReviewHeaderProps) => { - const { reviewDrawerCollapsed } = useAppSelector((state) => ({ - reviewDrawerCollapsed: - state?.reviewDrawerCollapsed !== undefined - ? state?.reviewDrawerCollapsed - : true, - })); - const { machineService, publishedReview, reviewTaskType } = useContext( ReviewTaskMachineContext ); diff --git a/src/components/ClaimReview/ClaimReviewView.tsx b/src/components/ClaimReview/ClaimReviewView.tsx index 278c889fc..8d3732d4c 100644 --- a/src/components/ClaimReview/ClaimReviewView.tsx +++ b/src/components/ClaimReview/ClaimReviewView.tsx @@ -18,6 +18,7 @@ import ReviewTaskAdminToolBar from "../Toolbar/ReviewTaskAdminToolBar"; import { useAppSelector } from "../../store/store"; import { ReviewTaskStates } from "../../machines/reviewTask/enums"; import { generateReviewContentPath } from "../../utils/GetReviewContentHref"; +import SentenceReportPreviewView from "../SentenceReport/SentenceReportPreviewView"; export interface ClaimReviewViewProps { content: Content; @@ -31,12 +32,15 @@ const ClaimReviewView = (props: ClaimReviewViewProps) => { const { machineService, publishedReview, reviewTaskType } = useContext( ReviewTaskMachineContext ); - const { reviewDrawerCollapsed } = useAppSelector((state) => ({ - reviewDrawerCollapsed: - state?.reviewDrawerCollapsed !== undefined - ? state?.reviewDrawerCollapsed - : true, - })); + const { vw, enableViewReportPreview, reviewDrawerCollapsed } = + useAppSelector((state) => ({ + vw: state?.vw, + enableViewReportPreview: state?.enableViewReportPreview, + reviewDrawerCollapsed: + state?.reviewDrawerCollapsed !== undefined + ? state?.reviewDrawerCollapsed + : true, + })); const { review } = publishedReview || {}; const reviewData = useSelector(machineService, reviewDataSelector); const [role] = useAtom(currentUserRole); @@ -44,8 +48,6 @@ const ClaimReviewView = (props: ClaimReviewViewProps) => { const [nameSpace] = useAtom(currentNameSpace); const userIsNotRegular = !(role === Roles.Regular || role === null); const userIsReviewer = reviewData.reviewerId === userId; - const userIsCrossChecker = reviewData.crossCheckerId === userId; - const userIsAssignee = reviewData.usersId.includes(userId); const hasStartedTask = machineService.state.value !== ReviewTaskStates.unassigned; const origin = window.location.origin ? window.location.origin : ""; @@ -90,25 +92,39 @@ const ClaimReviewView = (props: ClaimReviewViewProps) => { )} )} - - + {!vw?.sm && ( + + )} + + {enableViewReportPreview ? ( + + ) : ( + + )} {!review?.isPublished && ( { +const CommentContainer = ({ state, isCommentVisible, setIsCommentVisible }) => { const enableEditorAnnotations = useAppSelector( (state) => state?.enableEditorAnnotations ); const { comments, setComments } = useContext(VisualEditorContext); const { machineService } = useContext(ReviewTaskMachineContext); const reviewData = useSelector(machineService, reviewDataSelector); - const [role] = useAtom(currentUserRole); - const [isCommentVisible, setIsCommentVisible] = useState(false); const [userId] = useAtom(currentUserId); const hasSession = !!userId; const [user, setUser] = useState(null); - const { addAnnotation, setAnnotations } = useCommands(); + const { setAnnotations } = useCommands(); const { getAnnotations } = useHelpers(); - const enabled = enableEditorAnnotations - ? addAnnotation?.enabled({ id: "" }) - : true; const annotations = enableEditorAnnotations ? getAnnotations() : null; const crossCheckingComments = useMemo( () => @@ -69,7 +58,7 @@ const CommentContainer = ({ readonly, state }) => { useEffect(() => { if (enableEditorAnnotations) { if ( - (comments && annotations.length === 0) || + (comments && annotations?.length === 0) || state.doc.content.size === annotations[0]?.from ) { setAnnotations(comments); @@ -80,40 +69,26 @@ const CommentContainer = ({ readonly, state }) => { }, [setAnnotations, setComments, state.doc]); return ( - <> - {readonly && role !== Roles.Regular && role !== Roles.FactChecker && ( - - setIsCommentVisible(true)} - /> - + 0 ? "flex" : "none", + flexDirection: "column", + gap: 8, + }} + > + {isCommentVisible && ( + )} - 0 - ? "flex" - : "none", - flexDirection: "column", - gap: 8, - }} - > - {isCommentVisible && ( - - )} - - - + + ); }; diff --git a/src/components/Collaborative/Components/AffixPreviewButton.tsx b/src/components/Collaborative/Components/AffixPreviewButton.tsx new file mode 100644 index 000000000..3ee92e8c2 --- /dev/null +++ b/src/components/Collaborative/Components/AffixPreviewButton.tsx @@ -0,0 +1,46 @@ +import React, { useContext } from "react"; +import AletheiaButton from "../../Button"; +import { Affix } from "antd"; +import { ReviewTaskMachineContext } from "../../../machines/reviewTask/ReviewTaskMachineProvider"; +import { ReviewTaskEvents } from "../../../machines/reviewTask/enums"; +import { useTranslation } from "next-i18next"; + +const AffixPreviewButton = ({ doc }) => { + const { t } = useTranslation(); + const { machineService, viewPreview, handleClickViewPreview } = useContext( + ReviewTaskMachineContext + ); + + const handleOnClick = () => { + handleClickViewPreview(); + const payload = { + reviewData: { + visualEditor: doc, + }, + }; + machineService.send(ReviewTaskEvents.viewPreview, payload); + }; + + return ( + + + {viewPreview + ? t("claimReviewForm:hidePreview") + : t("claimReviewForm:viewPreview")} + + + ); +}; + +export default AffixPreviewButton; diff --git a/src/components/Collaborative/Components/ClaimReviewEditor.tsx b/src/components/Collaborative/Components/ClaimReviewEditor.tsx index 228a0a875..7d11d02d3 100644 --- a/src/components/Collaborative/Components/ClaimReviewEditor.tsx +++ b/src/components/Collaborative/Components/ClaimReviewEditor.tsx @@ -35,7 +35,6 @@ const ClaimReviewEditor = ({ manager, state, editorSources }) => { return ( <> - { + const [isCommentVisible, setIsCommentVisible] = useState(false); + const { + isEditing, + onRemoveLink, + submitHref, + href, + setHref, + cancelHref, + error, + isLoading, + clickEdit, + linkPositioner, + isSelected, + } = useFloatingLinkState(); + + const handleClickEditLink = useCallback(() => { + clickEdit(); + }, [clickEdit]); + + const onSelect = () => setIsCommentVisible(true); + + return ( + <> + + + + + ); +}; + +export default FloatingMenu; diff --git a/src/components/Collaborative/Components/FloatingMenuContent.tsx b/src/components/Collaborative/Components/FloatingMenuContent.tsx new file mode 100644 index 000000000..1b0a7c501 --- /dev/null +++ b/src/components/Collaborative/Components/FloatingMenuContent.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import CommentContainer from "../Comment/CommentContainer"; +import FloatingLinkToolbar from "./LinkToolBar/FloatingLinkToolbar"; + +const FloatingMenuContent = ({ + state, + isCommentVisible, + setIsCommentVisible, + isEditing, + onRemoveLink, + submitHref, + href, + setHref, + cancelHref, + error, + isLoading, +}) => { + return ( + <> + + + + ); +}; + +export default FloatingMenuContent; diff --git a/src/components/Collaborative/Components/FloatingMenuIcons.tsx b/src/components/Collaborative/Components/FloatingMenuIcons.tsx new file mode 100644 index 000000000..4ee400e66 --- /dev/null +++ b/src/components/Collaborative/Components/FloatingMenuIcons.tsx @@ -0,0 +1,68 @@ +import { + CommandButton, + FloatingToolbar, + useCommands, + useCurrentSelection, +} from "@remirror/react"; +import { useAtom } from "jotai"; +import React, { useContext } from "react"; +import { currentUserRole } from "../../../atoms/currentUser"; +import { Roles } from "../../../types/enums"; +import { useAppSelector } from "../../../store/store"; +import { ReviewTaskTypeEnum } from "../../../machines/reviewTask/enums"; +import { ReviewTaskMachineContext } from "../../../machines/reviewTask/ReviewTaskMachineProvider"; +import { useSelector } from "@xstate/react"; +import { reviewingSelector } from "../../../machines/reviewTask/selectors"; + +const FloatingMenuIcons = ({ + handleClickEditLink, + readonly, + linkPositioner, + isSelected, + isEditing, + onSelect, +}) => { + const { reviewTaskType, machineService } = useContext( + ReviewTaskMachineContext + ); + const enableEditorAnnotations = useAppSelector( + ({ enableEditorAnnotations }) => enableEditorAnnotations + ); + const [role] = useAtom(currentUserRole); + const { addAnnotation } = useCommands(); + const { empty } = useCurrentSelection(); + const isReviewing = useSelector(machineService, reviewingSelector); + const enabled = enableEditorAnnotations + ? addAnnotation?.enabled({ id: "" }) + : true; + + return ( + + {!readonly && reviewTaskType === ReviewTaskTypeEnum.Claim && ( + + )} + {isReviewing && + role !== Roles.Regular && + role !== Roles.FactChecker && ( + + )} + + ); +}; + +export default FloatingMenuIcons; diff --git a/src/components/Collaborative/Components/LinkToolBar/FloatingLinkToolbar.tsx b/src/components/Collaborative/Components/LinkToolBar/FloatingLinkToolbar.tsx index 687a26f81..e08589b66 100644 --- a/src/components/Collaborative/Components/LinkToolBar/FloatingLinkToolbar.tsx +++ b/src/components/Collaborative/Components/LinkToolBar/FloatingLinkToolbar.tsx @@ -1,42 +1,26 @@ import type { ChangeEvent, KeyboardEvent } from "react"; -import { - CommandButton, - FloatingToolbar, - FloatingWrapper, - useActive, - useCurrentSelection, -} from "@remirror/react"; -import React, { useCallback } from "react"; +import { FloatingWrapper, useActive } from "@remirror/react"; +import React from "react"; import SourceDialog from "./Dialog/SourceDialog"; -import useFloatingLinkState from "../../hooks/useFloatingLinkState"; import { useTranslation } from "next-i18next"; export const HTTP_PROTOCOL_REGEX = /(https?:\/\/)(https?:\/\/)+/; -const FloatingLinkToolbar = () => { - const { - isEditing, - linkPositioner, - clickEdit, - onRemoveLink, - submitHref, - href, - setHref, - isSelected, - cancelHref, - error, - isLoading, - } = useFloatingLinkState(); +const FloatingLinkToolbar = ({ + isEditing, + onRemoveLink, + submitHref, + href, + setHref, + cancelHref, + error, + isLoading, +}) => { const { t } = useTranslation(); - const { empty } = useCurrentSelection(); const active = useActive(); const activeLink = active.link(); - const handleClickEditLink = useCallback(() => { - clickEdit(); - }, [clickEdit]); - const handleInputChange = ({ target: { value }, }: ChangeEvent) => { @@ -59,57 +43,31 @@ const FloatingLinkToolbar = () => { }; const handleClickButton = () => submitHref(); - const handleCloseModal = () => cancelHref(); - const handleRemoveLink = () => onRemoveLink(); - const linkEditButton = ( - - ); - return ( - <> - {!isEditing && ( - - {linkEditButton} - - )} - {!isEditing && isSelected && empty && ( - - {linkEditButton} - - )} - - - - + + + ); }; diff --git a/src/components/Collaborative/VisualEditor.style.tsx b/src/components/Collaborative/VisualEditor.style.tsx index bd6b920dd..7bb992b78 100644 --- a/src/components/Collaborative/VisualEditor.style.tsx +++ b/src/components/Collaborative/VisualEditor.style.tsx @@ -27,6 +27,11 @@ const VisualEditorStyled = styled(AllStyledComponent)` .remirror-floating-popover { z-index: 2; } + + .ant-affix { + display: flex; + justify-content: center; + } `; export default VisualEditorStyled; diff --git a/src/components/Collaborative/VisualEditor.tsx b/src/components/Collaborative/VisualEditor.tsx index f905a79b5..4d6cf12a5 100644 --- a/src/components/Collaborative/VisualEditor.tsx +++ b/src/components/Collaborative/VisualEditor.tsx @@ -5,7 +5,8 @@ import VisualEditorStyled from "./VisualEditor.style"; import { ReviewTaskMachineContext } from "../../machines/reviewTask/ReviewTaskMachineProvider"; import { EditorConfig } from "./utils/getEditorConfig"; import Editor from "./Components/Editor"; -import CommentContainer from "./Comment/CommentContainer"; +import FloatingMenu from "./Components/FloatingMenu"; +import AffixPreviewButton from "./Components/AffixPreviewButton"; interface VisualEditorProps { onContentChange: (state: any, type: string) => void; @@ -41,9 +42,10 @@ const VisualEditor = ({ onContentChange }: VisualEditorProps) => { editable={!readonly} > {getComponents(reviewTaskType, getComponentsProps)} - + + ); }; diff --git a/src/components/Collaborative/VisualEditorProvider.tsx b/src/components/Collaborative/VisualEditorProvider.tsx index d0dae1ff1..992a04c1b 100644 --- a/src/components/Collaborative/VisualEditorProvider.tsx +++ b/src/components/Collaborative/VisualEditorProvider.tsx @@ -6,7 +6,11 @@ import { RemirrorContentType } from "remirror"; import { SourceType } from "../../types/Source"; import { ReviewTaskMachineContext } from "../../machines/reviewTask/ReviewTaskMachineProvider"; import { EditorConfig } from "./utils/getEditorConfig"; -import { reviewingSelector } from "../../machines/reviewTask/selectors"; +import { + crossCheckingSelector, + reportSelector, + reviewingSelector, +} from "../../machines/reviewTask/selectors"; import { useSelector } from "@xstate/react"; interface ContextType { @@ -33,12 +37,17 @@ export const VisualEditorProvider = (props: VisualEditorProviderProps) => { const { machineService, reportModel, reviewTaskType } = useContext( ReviewTaskMachineContext ); - const { enableCollaborativeEdit, enableEditorAnnotations, websocketUrl } = - useAppSelector((state) => ({ - enableCollaborativeEdit: state?.enableCollaborativeEdit, - enableEditorAnnotations: state?.enableEditorAnnotations, - websocketUrl: state?.websocketUrl, - })); + const { + enableCollaborativeEdit, + enableEditorAnnotations, + websocketUrl, + enableReviewersUpdateReport, + } = useAppSelector((state) => ({ + enableCollaborativeEdit: state?.enableCollaborativeEdit, + enableEditorAnnotations: state?.enableEditorAnnotations, + enableReviewersUpdateReport: state?.enableReviewersUpdateReport, + websocketUrl: state?.websocketUrl, + })); const [editorContentObject, setEditorContentObject] = useState(null); const [editorSources, setEditorSources] = useState( @@ -46,7 +55,13 @@ export const VisualEditorProvider = (props: VisualEditorProviderProps) => { ); const [isFetchingEditor, setIsFetchingEditor] = useState(false); const [comments, setComments] = useState(null); - const readonly = useSelector(machineService, reviewingSelector); + const isReviewing = useSelector(machineService, reviewingSelector); + const isReported = useSelector(machineService, reportSelector); + const isCrossChecking = useSelector(machineService, crossCheckingSelector); + const readonly = + isReported || + isCrossChecking || + (isReviewing && !enableReviewersUpdateReport); useEffect(() => { const params = { reportModel, reviewTaskType }; diff --git a/src/components/SentenceReport/SentenceReportCard.tsx b/src/components/SentenceReport/SentenceReportCard.tsx index 1affe5275..b7affbe80 100644 --- a/src/components/SentenceReport/SentenceReportCard.tsx +++ b/src/components/SentenceReport/SentenceReportCard.tsx @@ -42,7 +42,10 @@ const SentenceReportCard = ({ {personality && ( - + )} { + const [isLoggedIn] = useAtom(isUserLoggedIn); + return ( + + {canShowReportPreview && ( + + )} + + {!isLoggedIn && } + + ); +}; + +export default SentenceReportPreview; diff --git a/src/components/SentenceReport/SentenceReportPreviewView.tsx b/src/components/SentenceReport/SentenceReportPreviewView.tsx new file mode 100644 index 000000000..0ccc29aad --- /dev/null +++ b/src/components/SentenceReport/SentenceReportPreviewView.tsx @@ -0,0 +1,147 @@ +import { useSelector } from "@xstate/react"; +import { Col, Row } from "antd"; +import React, { useContext } from "react"; + +import { ReviewTaskMachineContext } from "../../machines/reviewTask/ReviewTaskMachineProvider"; +import { Roles } from "../../types/enums"; +import { + reviewingSelector, + publishedSelector, + crossCheckingSelector, + reportSelector, +} from "../../machines/reviewTask/selectors"; +import colors from "../../styles/colors"; +import { useAtom } from "jotai"; +import { currentUserId, currentUserRole } from "../../atoms/currentUser"; +import { ReviewTaskTypeEnum } from "../../../server/types/enums"; +import LargeDrawer from "../LargeDrawer"; +import SentenceReportPreview from "./SentenceReportPreview"; +import { useAppSelector } from "../../store/store"; +import ClaimReviewHeader from "../ClaimReview/ClaimReviewHeader"; +import { Content } from "../../types/Content"; + +interface ISentenceReportViewV1Props { + context: any; + userIsNotRegular: boolean; + userIsReviewer: boolean; + isHidden: boolean; + href: string; + componentStyle: any; + personality?: any; + content: Content; + target?: any; + hideDescriptions?: any; +} + +const SentenceReportPreviewView = ({ + context, + userIsNotRegular, + userIsReviewer, + isHidden, + href, + componentStyle, + personality, + content, + target, + hideDescriptions, +}: ISentenceReportViewV1Props) => { + const { reviewDrawerCollapsed } = useAppSelector((state) => ({ + reviewDrawerCollapsed: + state?.reviewDrawerCollapsed !== undefined + ? state?.reviewDrawerCollapsed + : true, + })); + const [role] = useAtom(currentUserRole); + const [userId] = useAtom(currentUserId); + const { + machineService, + publishedReview, + reviewTaskType, + viewPreview, + handleClickViewPreview, + } = useContext(ReviewTaskMachineContext); + const isReport = useSelector(machineService, reportSelector); + const isCrossChecking = useSelector(machineService, crossCheckingSelector); + const isReviewing = useSelector(machineService, reviewingSelector); + const isPublished = + useSelector(machineService, publishedSelector) || + publishedReview?.review; + const userIsAdmin = role === Roles.Admin || role === Roles.SuperAdmin; + const userIsCrossChecker = context.crossCheckerId === userId; + const userIsAssignee = context.usersId.includes(userId); + + const isCrossCheckingAndUserHasPermission = + isCrossChecking && (userIsAdmin || userIsCrossChecker); + const isReviewingAndUserHasPermission = + isReviewing && (userIsAdmin || userIsReviewer); + const isReportedAndUserHasPermission = + isReport && (userIsAdmin || userIsAssignee || userIsCrossChecker); + const canShowReportPreview = + isCrossCheckingAndUserHasPermission || + isReviewingAndUserHasPermission || + isReportedAndUserHasPermission; + const canShowReport = + (isPublished && (!isHidden || userIsNotRegular)) || + (canShowReportPreview && viewPreview && !reviewDrawerCollapsed); + + return ( + reviewTaskType !== ReviewTaskTypeEnum.VerificationRequest && ( + + {canShowReport && ( + + )} + + {reviewDrawerCollapsed && ( + + + + + + + )} + + ) + ); +}; + +export default SentenceReportPreviewView; diff --git a/src/components/SentenceReport/SentenceReportSummary.tsx b/src/components/SentenceReport/SentenceReportSummary.tsx index 3af8babc5..4dd827f31 100644 --- a/src/components/SentenceReport/SentenceReportSummary.tsx +++ b/src/components/SentenceReport/SentenceReportSummary.tsx @@ -12,6 +12,7 @@ const SentenceReportSummary = styled(Row)` align-items: center; justify-content: space-between; background-color: ${colors.lightYellow}; + width: fit-content; // small triangle pointing to the avatar on the side &.after:after { diff --git a/src/components/SentenceReport/SentenceReportView.tsx b/src/components/SentenceReport/SentenceReportView.tsx index 85095be1e..f7eafb41b 100644 --- a/src/components/SentenceReport/SentenceReportView.tsx +++ b/src/components/SentenceReport/SentenceReportView.tsx @@ -14,7 +14,11 @@ import colors from "../../styles/colors"; import CTARegistration from "../Home/CTARegistration"; import SentenceReportContent from "./SentenceReportContent"; import { useAtom } from "jotai"; -import { currentUserRole, isUserLoggedIn } from "../../atoms/currentUser"; +import { + currentUserId, + currentUserRole, + isUserLoggedIn, +} from "../../atoms/currentUser"; import SentenceReportComments from "./SentenceReportComments"; import { ReviewTaskTypeEnum } from "../../../server/types/enums"; @@ -23,16 +27,17 @@ const SentenceReportView = ({ userIsNotRegular, userIsReviewer, isHidden, - userIsAssignee, - userIsCrossChecker, href, componentStyle, }) => { const [isLoggedIn] = useAtom(isUserLoggedIn); const [role] = useAtom(currentUserRole); + const [userId] = useAtom(currentUserId); const { machineService, publishedReview, reviewTaskType } = useContext( ReviewTaskMachineContext ); + const userIsCrossChecker = context.crossCheckerId === userId; + const userIsAssignee = context.usersId.includes(userId); const isReport = useSelector(machineService, reportSelector); const isCrossChecking = useSelector(machineService, crossCheckingSelector); const isReviewing = useSelector(machineService, reviewingSelector); diff --git a/src/machines/reviewTask/ReviewTaskMachineProvider.tsx b/src/machines/reviewTask/ReviewTaskMachineProvider.tsx index 63757512c..20b49e8d6 100644 --- a/src/machines/reviewTask/ReviewTaskMachineProvider.tsx +++ b/src/machines/reviewTask/ReviewTaskMachineProvider.tsx @@ -24,6 +24,8 @@ interface ContextType { recreateMachine?: (reportModel: string) => void; claim?: any; sentenceContent?: any; + viewPreview?: boolean; + handleClickViewPreview?: () => void; } export const ReviewTaskMachineContext = createContext({ @@ -77,6 +79,7 @@ export const ReviewTaskMachineProvider = ( const [form, setForm] = useState(null); const [events, setEvents] = useState(null); const [loading, setLoading] = useState(false); + const [viewPreview, setViewPreview] = useState(false); const [reportModel, setReportModel] = useState( props.baseReportModel ); @@ -171,6 +174,8 @@ export const ReviewTaskMachineProvider = ( setLoading(false); }; + const handleClickViewPreview = () => setViewPreview((prev) => !prev); + return ( {loading && } diff --git a/src/machines/reviewTask/actions.ts b/src/machines/reviewTask/actions.ts index c15d61f4e..4056f0a5a 100644 --- a/src/machines/reviewTask/actions.ts +++ b/src/machines/reviewTask/actions.ts @@ -7,9 +7,15 @@ import { ReviewTaskEvents } from "./enums"; const saveContext = assign( (context, event) => { const editorParser = new EditorParser(); + const supportedEvents = [ + ReviewTaskEvents.finishReport, + ReviewTaskEvents.draft, + ReviewTaskEvents.addRejectionComment, + ReviewTaskEvents.viewPreview, + ]; + if ( - (event.type === ReviewTaskEvents.finishReport || - event.type === ReviewTaskEvents.draft) && + supportedEvents.includes(event.type as ReviewTaskEvents) && "visualEditor" in event.reviewData ) { const schema = editorParser.editor2schema( diff --git a/src/machines/reviewTask/enums.ts b/src/machines/reviewTask/enums.ts index 11c2a3efe..2c396ab42 100644 --- a/src/machines/reviewTask/enums.ts +++ b/src/machines/reviewTask/enums.ts @@ -18,6 +18,7 @@ enum ReviewTaskEvents { reset = "RESET", rejectRequest = "REJECT_REQUEST", assignRequest = "ASSIGN_REQUEST", + viewPreview = "VIEW_PREVIEW", } enum KanbanVerificationRequestStates { diff --git a/src/machines/reviewTask/getNextEvent.ts b/src/machines/reviewTask/getNextEvent.ts index a6d4adcb5..0aa9f6f72 100644 --- a/src/machines/reviewTask/getNextEvent.ts +++ b/src/machines/reviewTask/getNextEvent.ts @@ -76,10 +76,9 @@ const getNextEvents = ( ? [Events.goback, Events.sendToCrossChecking, Events.selectedReview] : [...defaultEvents, Events.finishReport], - [States.submitted]: [Events.reject, Events.publish], - [Events.sendToReview]: [Events.reject, Events.publish], + [States.submitted]: [Events.addRejectionComment, Events.publish], + [Events.sendToReview]: [Events.addRejectionComment, Events.publish], - [States.rejected]: [Events.goback, Events.addRejectionComment], [Events.addRejectionComment]: reportModel === ReportModelEnum.FactChecking ? [...defaultEvents, Events.finishReport] diff --git a/src/machines/reviewTask/getNextForm.ts b/src/machines/reviewTask/getNextForm.ts index 83cce84fd..6a9ac2a67 100644 --- a/src/machines/reviewTask/getNextForm.ts +++ b/src/machines/reviewTask/getNextForm.ts @@ -3,7 +3,6 @@ import { ReviewTaskEvents, ReviewTaskStates } from "./enums"; import visualEditor from "../../components/ClaimReview/form/fieldLists/visualEditor"; import selectReviewer from "../../components/ClaimReview/form/fieldLists/selectReviewerForm"; import unassignedForm from "../../components/ClaimReview/form/fieldLists/unassignedForm"; -import submittedForm from "../../components/ClaimReview/form/fieldLists/submittedForm"; import crossCheckingForm from "../../components/ClaimReview/form/fieldLists/crossCheckingForm"; import selectCrossCheckerForm from "../../components/ClaimReview/form/fieldLists/selectCrossCheckerForm"; import verificationRequestForm from "../../components/ClaimReview/form/fieldLists/verificationRequestForm"; @@ -19,9 +18,9 @@ const getNextForm = ( [ReviewTaskEvents.assignRequest]: verificationRequestForm, [ReviewTaskStates.assignedRequest]: verificationRequestForm, - [ReviewTaskEvents.finishReport]: [], - [ReviewTaskStates.reported]: [], - [ReviewTaskEvents.submitCrossChecking]: [], + [ReviewTaskEvents.finishReport]: visualEditor, + [ReviewTaskStates.reported]: visualEditor, + [ReviewTaskEvents.submitCrossChecking]: visualEditor, [ReviewTaskEvents.selectedCrossChecking]: selectCrossCheckerForm, [ReviewTaskStates.selectCrossChecker]: selectCrossCheckerForm, @@ -29,17 +28,16 @@ const getNextForm = ( [ReviewTaskEvents.selectedReview]: selectReviewer, [ReviewTaskStates.selectReviewer]: selectReviewer, - [ReviewTaskEvents.sendToCrossChecking]: [], - [ReviewTaskStates.crossChecking]: [], + [ReviewTaskEvents.sendToCrossChecking]: visualEditor, + [ReviewTaskStates.crossChecking]: visualEditor, [ReviewTaskEvents.addComment]: crossCheckingForm, [ReviewTaskStates.addCommentCrossChecking]: crossCheckingForm, - [ReviewTaskEvents.submitComment]: isSameLabel ? [] : visualEditor, + [ReviewTaskEvents.submitComment]: visualEditor, - [ReviewTaskEvents.sendToReview]: [], - [ReviewTaskStates.submitted]: [], - [ReviewTaskStates.rejected]: submittedForm, + [ReviewTaskEvents.sendToReview]: visualEditor, + [ReviewTaskStates.submitted]: visualEditor, [ReviewTaskEvents.addRejectionComment]: visualEditor, [ReviewTaskStates.published]: [], [ReviewTaskEvents.publish]: [], diff --git a/src/machines/reviewTask/machineWorkflow.ts b/src/machines/reviewTask/machineWorkflow.ts index 864e25c9f..7ed52816a 100644 --- a/src/machines/reviewTask/machineWorkflow.ts +++ b/src/machines/reviewTask/machineWorkflow.ts @@ -65,6 +65,10 @@ const factCheckingWorkflow: StatesConfig< target: States.reported, actions: [saveContext], }, + [Events.viewPreview]: { + target: States.assigned, + actions: [saveContext], + }, }, }, [States.reported]: { @@ -81,6 +85,10 @@ const factCheckingWorkflow: StatesConfig< [Events.selectedReview]: { target: States.selectReviewer, }, + [Events.viewPreview]: { + target: States.reported, + actions: [saveContext], + }, }, }, [States.selectCrossChecker]: { @@ -95,6 +103,10 @@ const factCheckingWorkflow: StatesConfig< target: States.crossChecking, actions: [saveContext], }, + [Events.viewPreview]: { + target: States.selectCrossChecker, + actions: [saveContext], + }, }, }, [States.selectReviewer]: { @@ -109,6 +121,10 @@ const factCheckingWorkflow: StatesConfig< target: States.submitted, actions: [saveContext], }, + [Events.viewPreview]: { + target: States.selectReviewer, + actions: [saveContext], + }, }, }, [States.crossChecking]: { @@ -124,6 +140,10 @@ const factCheckingWorkflow: StatesConfig< target: States.reported, actions: [saveContext], }, + [Events.viewPreview]: { + target: States.crossChecking, + actions: [saveContext], + }, }, }, [States.addCommentCrossChecking]: { @@ -146,13 +166,18 @@ const factCheckingWorkflow: StatesConfig< cond: isDifferentLabel, }, ], + [Events.viewPreview]: { + target: States.addCommentCrossChecking, + actions: [saveContext], + }, }, }, //TODO: Investigate how to move rejected and addComment crossChecking as substates [States.submitted]: { on: { - [Events.reject]: { - target: States.rejected, + [Events.addRejectionComment]: { + target: States.assigned, + actions: [saveContext], }, [Events.reAssignUser]: { target: States.unassigned, @@ -161,19 +186,9 @@ const factCheckingWorkflow: StatesConfig< target: States.published, actions: [saveContext], }, - }, - }, - [States.rejected]: { - on: { - [Events.addRejectionComment]: { - target: States.assigned, - actions: [saveContext], - }, - [Events.reAssignUser]: { - target: States.unassigned, - }, - [Events.goback]: { + [Events.viewPreview]: { target: States.submitted, + actions: [saveContext], }, }, }, diff --git a/src/machines/reviewTask/reviewTaskMachine.ts b/src/machines/reviewTask/reviewTaskMachine.ts index 9c5e38311..71b405fe2 100644 --- a/src/machines/reviewTask/reviewTaskMachine.ts +++ b/src/machines/reviewTask/reviewTaskMachine.ts @@ -52,7 +52,7 @@ export const transitionHandler = (state) => { event === Events.selectedReview || event === Events.reAssignUser; - if (event === Events.init) { + if (event === Events.init || event === Events.viewPreview) { return; } diff --git a/src/pages/claim-page.tsx b/src/pages/claim-page.tsx index b16981f6d..bfcc99cac 100644 --- a/src/pages/claim-page.tsx +++ b/src/pages/claim-page.tsx @@ -22,6 +22,7 @@ export interface ClaimPageProps { enableCopilotChatBot: boolean; enableEditorAnnotations: boolean; enableAddEditorSourcesWithoutSelecting: boolean; + enableReviewersUpdateReport: boolean; hideDescriptions: object; websocketUrl: string; nameSpace: NameSpaceEnum; @@ -35,6 +36,8 @@ const ClaimPage: NextPage = (props) => { enableCollaborativeEditor, enableCopilotChatBot, enableEditorAnnotations, + enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, } = props; const setCurrentNameSpace = useSetAtom(currentNameSpace); const { t } = useTranslation(); @@ -44,23 +47,16 @@ const ClaimPage: NextPage = (props) => { dispatch(actions.setWebsocketUrl(props.websocketUrl)); dispatch(actions.setSitekey(sitekey)); dispatch(actions.closeCopilotDrawer()); - dispatch({ - type: ActionTypes.SET_COLLABORATIVE_EDIT, - enableCollaborativeEdit: enableCollaborativeEditor, - }); - dispatch({ - type: ActionTypes.SET_COPILOT_CHAT_BOT, - enableCopilotChatBot: enableCopilotChatBot, - }); - dispatch({ - type: ActionTypes.SET_EDITOR_ANNOTATION, - enableEditorAnnotations: enableEditorAnnotations, - }); - dispatch({ - type: ActionTypes.SET_ADD_EDITOR_SOURCES_WITHOUT_SELECTING, - enableAddEditorSourcesWithoutSelecting: - props.enableAddEditorSourcesWithoutSelecting, - }); + dispatch( + actions.setEditorEnvironment( + enableCollaborativeEditor, + enableAddEditorSourcesWithoutSelecting, + enableEditorAnnotations, + enableCopilotChatBot, + false, + enableReviewersUpdateReport + ) + ); const jsonld = { "@context": "https://schema.org", @@ -112,6 +108,7 @@ export async function getServerSideProps({ query, locale, locales, req }) { enableEditorAnnotations: query?.enableEditorAnnotations, enableAddEditorSourcesWithoutSelecting: query?.enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport: query?.enableReviewersUpdateReport, websocketUrl: query.websocketUrl, nameSpace: query.nameSpace ? query.nameSpace : NameSpaceEnum.Main, }, diff --git a/src/pages/claim-review.tsx b/src/pages/claim-review.tsx index 6bbebd3b5..14e9fdee1 100644 --- a/src/pages/claim-review.tsx +++ b/src/pages/claim-review.tsx @@ -31,6 +31,8 @@ export interface ClaimReviewPageProps { enableCopilotChatBot: boolean; enableEditorAnnotations: boolean; enableAddEditorSourcesWithoutSelecting: boolean; + enableReviewersUpdateReport: boolean; + enableViewReportPreview: boolean; websocketUrl: string; nameSpace: string; } @@ -49,33 +51,26 @@ const ClaimReviewPage: NextPage = (props) => { enableCollaborativeEditor, enableCopilotChatBot, enableEditorAnnotations, + enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, + enableViewReportPreview, hideDescriptions, } = props; dispatch(actions.setWebsocketUrl(props.websocketUrl)); dispatch(actions.setSitekey(sitekey)); dispatch(actions.closeCopilotDrawer()); - dispatch({ - type: ActionTypes.SET_AUTO_SAVE, - autoSave: false, - }); - dispatch({ - type: ActionTypes.SET_COLLABORATIVE_EDIT, - enableCollaborativeEdit: enableCollaborativeEditor, - }); - dispatch({ - type: ActionTypes.SET_COPILOT_CHAT_BOT, - enableCopilotChatBot: enableCopilotChatBot, - }); - dispatch({ - type: ActionTypes.SET_EDITOR_ANNOTATION, - enableEditorAnnotations: enableEditorAnnotations, - }); - dispatch({ - type: ActionTypes.SET_ADD_EDITOR_SOURCES_WITHOUT_SELECTING, - enableAddEditorSourcesWithoutSelecting: - props.enableAddEditorSourcesWithoutSelecting, - }); + dispatch( + actions.setEditorEnvironment( + enableCollaborativeEditor, + enableAddEditorSourcesWithoutSelecting, + enableEditorAnnotations, + enableCopilotChatBot, + false, + enableReviewersUpdateReport, + enableViewReportPreview + ) + ); const isImage = claim?.contentModel === ContentModelEnum.Image; const review = content?.props?.classification; @@ -170,6 +165,8 @@ export async function getServerSideProps({ query, locale, locales, req }) { enableEditorAnnotations: query?.enableEditorAnnotations, enableAddEditorSourcesWithoutSelecting: query?.enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport: query?.enableReviewersUpdateReport, + enableViewReportPreview: query?.enableViewReportPreview, websocketUrl: query?.websocketUrl, nameSpace: query.nameSpace ? query.nameSpace : NameSpaceEnum.Main, }, diff --git a/src/pages/kanban-page.tsx b/src/pages/kanban-page.tsx index 50af94356..58a8ace9a 100644 --- a/src/pages/kanban-page.tsx +++ b/src/pages/kanban-page.tsx @@ -23,6 +23,8 @@ const KanbanPage: NextPage<{ enableCopilotChatBot: boolean; enableEditorAnnotations: boolean; enableAddEditorSourcesWithoutSelecting: boolean; + enableReviewersUpdateReport: boolean; + enableViewReportPreview: boolean; websocketUrl: string; nameSpace: NameSpaceEnum; }> = (props) => { @@ -33,27 +35,17 @@ const KanbanPage: NextPage<{ dispatch(actions.setSitekey(props.sitekey)); dispatch(actions.setWebsocketUrl(props.websocketUrl)); dispatch(actions.closeCopilotDrawer()); - dispatch({ - type: ActionTypes.SET_COLLABORATIVE_EDIT, - enableCollaborativeEdit: props.enableCollaborativeEditor, - }); - dispatch({ - type: ActionTypes.SET_COPILOT_CHAT_BOT, - enableCopilotChatBot: props.enableCopilotChatBot, - }); - dispatch({ - type: ActionTypes.SET_EDITOR_ANNOTATION, - enableEditorAnnotations: props.enableEditorAnnotations, - }); - dispatch({ - type: ActionTypes.SET_ADD_EDITOR_SOURCES_WITHOUT_SELECTING, - enableAddEditorSourcesWithoutSelecting: + dispatch( + actions.setEditorEnvironment( + props.enableCollaborativeEditor, props.enableAddEditorSourcesWithoutSelecting, - }); - dispatch({ - type: ActionTypes.SET_AUTO_SAVE, - autoSave: false, - }); + props.enableEditorAnnotations, + props.enableCopilotChatBot, + false, + props.enableReviewersUpdateReport, + props.enableViewReportPreview + ) + ); const [value, setValue] = React.useState(null); const handleChange = (_event: React.SyntheticEvent, newValue: number) => { @@ -92,6 +84,8 @@ export async function getServerSideProps({ locale, locales, req, query }) { enableEditorAnnotations: query?.enableEditorAnnotations, enableAddEditorSourcesWithoutSelecting: query?.enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport: query?.enableReviewersUpdateReport, + enableViewReportPreview: query?.enableViewReportPreview, websocketUrl: query.websocketUrl, nameSpace: query.nameSpace ? query.nameSpace : NameSpaceEnum.Main, }, diff --git a/src/pages/source-review.tsx b/src/pages/source-review.tsx index 55cc16bbb..c65ee1124 100644 --- a/src/pages/source-review.tsx +++ b/src/pages/source-review.tsx @@ -27,6 +27,8 @@ export interface SourceReviewPageProps { enableCopilotChatBot: boolean; enableEditorAnnotations: boolean; enableAddEditorSourcesWithoutSelecting: boolean; + enableReviewersUpdateReport: boolean; + enableViewReportPreview: boolean; websocketUrl: string; nameSpace: string; } @@ -43,33 +45,26 @@ const SourceReviewPage: NextPage = (props) => { enableCollaborativeEditor, enableCopilotChatBot, enableEditorAnnotations, + enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport, + enableViewReportPreview, hideDescriptions, } = props; dispatch(actions.setWebsocketUrl(props.websocketUrl)); dispatch(actions.setSitekey(sitekey)); dispatch(actions.closeCopilotDrawer()); - dispatch({ - type: ActionTypes.SET_AUTO_SAVE, - autoSave: false, - }); - dispatch({ - type: ActionTypes.SET_COLLABORATIVE_EDIT, - enableCollaborativeEdit: enableCollaborativeEditor, - }); - dispatch({ - type: ActionTypes.SET_COPILOT_CHAT_BOT, - enableCopilotChatBot: enableCopilotChatBot, - }); - dispatch({ - type: ActionTypes.SET_EDITOR_ANNOTATION, - enableEditorAnnotations: enableEditorAnnotations, - }); - dispatch({ - type: ActionTypes.SET_ADD_EDITOR_SOURCES_WITHOUT_SELECTING, - enableAddEditorSourcesWithoutSelecting: - props.enableAddEditorSourcesWithoutSelecting, - }); + dispatch( + actions.setEditorEnvironment( + enableCollaborativeEditor, + enableAddEditorSourcesWithoutSelecting, + enableEditorAnnotations, + enableCopilotChatBot, + false, + enableReviewersUpdateReport, + enableViewReportPreview + ) + ); const review = source?.props?.classification; @@ -147,6 +142,8 @@ export async function getServerSideProps({ query, locale, locales, req }) { enableEditorAnnotations: query?.enableEditorAnnotations, enableAddEditorSourcesWithoutSelecting: query?.enableAddEditorSourcesWithoutSelecting, + enableReviewersUpdateReport: query?.enableReviewersUpdateReport, + enableViewReportPreview: query?.enableViewReportPreview, websocketUrl: query?.websocketUrl, nameSpace: query.nameSpace ? query.nameSpace : NameSpaceEnum.Main, }, diff --git a/src/store/actions.ts b/src/store/actions.ts index e4081f5a8..0ce91f046 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -56,6 +56,26 @@ const actions = { type: ActionTypes.SET_WEBSOCKET_URL, websocketUrl, }), + setEditorEnvironment: ( + enableCollaborativeEdit, + enableAddEditorSourcesWithoutSelecting, + enableEditorAnnotations, + enableCopilotChatBot, + autoSave, + enableReviewersUpdateReport, + enableViewReportPreview + ) => { + return { + type: ActionTypes.SET_VISUAL_EDITOR_ENVIRONEMNT, + enableCollaborativeEdit, + enableAddEditorSourcesWithoutSelecting, + enableEditorAnnotations, + enableCopilotChatBot, + autoSave, + enableReviewersUpdateReport, + enableViewReportPreview, + }; + }, }; export default actions; diff --git a/src/store/store.ts b/src/store/store.ts index d450fa201..20178e0ad 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -124,36 +124,22 @@ const reducer = (state, action) => { ...state, login: action.login, }; - case ActionTypes.SET_AUTO_SAVE: - return { - ...state, - autoSave: action.autoSave, - }; case ActionTypes.SET_WEBSOCKET_URL: return { ...state, websocketUrl: action.websocketUrl, }; - case ActionTypes.SET_COLLABORATIVE_EDIT: - return { - ...state, - enableCollaborativeEdit: action.enableCollaborativeEdit, - }; - case ActionTypes.SET_COPILOT_CHAT_BOT: - return { - ...state, - enableCopilotChatBot: action.enableCopilotChatBot, - }; - case ActionTypes.SET_EDITOR_ANNOTATION: - return { - ...state, - enableEditorAnnotations: action.enableEditorAnnotations, - }; - case ActionTypes.SET_ADD_EDITOR_SOURCES_WITHOUT_SELECTING: + case ActionTypes.SET_VISUAL_EDITOR_ENVIRONEMNT: return { ...state, enableAddEditorSourcesWithoutSelecting: action.enableAddEditorSourcesWithoutSelecting, + enableEditorAnnotations: action.enableEditorAnnotations, + enableCopilotChatBot: action.enableCopilotChatBot, + enableCollaborativeEdit: action.enableCollaborativeEdit, + autoSave: action.autoSave, + enableReviewersUpdateReport: action.enableReviewersUpdateReport, + enableViewReportPreview: action.enableViewReportPreview, }; case ActionTypes.SET_USER_ROLE: return { diff --git a/src/store/types.ts b/src/store/types.ts index 4699ca6f1..4e6368f56 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -14,7 +14,6 @@ export enum ActionTypes { SET_CUR_PAGE, SET_SEARCH_NAME, SET_LOGIN_STATUS, - SET_AUTO_SAVE, SET_BREAKPOINTS, SET_USER_ROLE, SET_CLAIM_CREATE_TYPE, @@ -30,10 +29,7 @@ export enum ActionTypes { RESULTS_TOPICS_AUTOCOMPLETE, SET_SEARCH_FILTER, SET_SEARCH_FILTER_USED, - SET_COLLABORATIVE_EDIT, - SET_COPILOT_CHAT_BOT, - SET_EDITOR_ANNOTATION, - SET_ADD_EDITOR_SOURCES_WITHOUT_SELECTING, + SET_VISUAL_EDITOR_ENVIRONEMNT, } export enum SearchTypes { @@ -65,6 +61,8 @@ export interface RootState { enableCopilotChatBot: boolean; enableEditorAnnotations: boolean; enableAddEditorSourcesWithoutSelecting: boolean; + enableReviewersUpdateReport: boolean; + enableViewReportPreview: boolean; websocketUrl: string; claimType: string; claimPersonality: Personality; From 8e3eb527c426a282e5d533f80aa13ec601643468 Mon Sep 17 00:00:00 2001 From: pepermao Date: Tue, 16 Jul 2024 19:20:48 +0200 Subject: [PATCH 3/5] fixed build --- src/components/TextAreaAutoSize.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TextAreaAutoSize.tsx b/src/components/TextAreaAutoSize.tsx index c4ec3b447..cbf5f2a5a 100644 --- a/src/components/TextAreaAutoSize.tsx +++ b/src/components/TextAreaAutoSize.tsx @@ -1,6 +1,6 @@ import styled from "styled-components"; import colors from "../styles/colors"; -import { TextareaAutosize } from "@mui/base"; +import { TextareaAutosize } from "@mui/material"; const AletheiaTextAreaAutoSize = styled(TextareaAutosize)` background: ${(props) => (props.white ? colors.white : colors.lightGray)}; From 6ce46d249d85c9fdbb3aab108acf9898c9745f72 Mon Sep 17 00:00:00 2001 From: pepermao Date: Wed, 17 Jul 2024 12:21:12 +0200 Subject: [PATCH 4/5] Fixed source review workflow cypress tests --- .../Collaborative/Components/FloatingMenu.tsx | 21 +++++++++++-------- src/components/Collaborative/VisualEditor.tsx | 6 +++++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/components/Collaborative/Components/FloatingMenu.tsx b/src/components/Collaborative/Components/FloatingMenu.tsx index c4854a231..76f73ce89 100644 --- a/src/components/Collaborative/Components/FloatingMenu.tsx +++ b/src/components/Collaborative/Components/FloatingMenu.tsx @@ -2,8 +2,9 @@ import React, { useCallback, useState } from "react"; import useFloatingLinkState from "../hooks/useFloatingLinkState"; import FloatingMenuIcons from "./FloatingMenuIcons"; import FloatingMenuContent from "./FloatingMenuContent"; +import { ReviewTaskTypeEnum } from "../../../machines/reviewTask/enums"; -const FloatingMenu = ({ readonly, state }) => { +const FloatingMenu = ({ readonly, state, reviewTaskType }) => { const [isCommentVisible, setIsCommentVisible] = useState(false); const { isEditing, @@ -27,14 +28,16 @@ const FloatingMenu = ({ readonly, state }) => { return ( <> - + {reviewTaskType === ReviewTaskTypeEnum.Claim && ( + + )} { editable={!readonly} > {getComponents(reviewTaskType, getComponentsProps)} - + From 8367e53454c5292cbe43fd1fb50d8f5204026cce Mon Sep 17 00:00:00 2001 From: pepermao Date: Wed, 17 Jul 2024 14:26:35 +0200 Subject: [PATCH 5/5] Fixed cypress tests --- .../Collaborative/Components/FloatingMenu.tsx | 20 +++++++-------- .../Components/FloatingMenuContent.tsx | 25 +++++++++++-------- .../Collaborative/utils/getEditorConfig.tsx | 14 ++++++----- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/components/Collaborative/Components/FloatingMenu.tsx b/src/components/Collaborative/Components/FloatingMenu.tsx index 76f73ce89..be9178e99 100644 --- a/src/components/Collaborative/Components/FloatingMenu.tsx +++ b/src/components/Collaborative/Components/FloatingMenu.tsx @@ -2,7 +2,6 @@ import React, { useCallback, useState } from "react"; import useFloatingLinkState from "../hooks/useFloatingLinkState"; import FloatingMenuIcons from "./FloatingMenuIcons"; import FloatingMenuContent from "./FloatingMenuContent"; -import { ReviewTaskTypeEnum } from "../../../machines/reviewTask/enums"; const FloatingMenu = ({ readonly, state, reviewTaskType }) => { const [isCommentVisible, setIsCommentVisible] = useState(false); @@ -28,16 +27,14 @@ const FloatingMenu = ({ readonly, state, reviewTaskType }) => { return ( <> - {reviewTaskType === ReviewTaskTypeEnum.Claim && ( - - )} + { cancelHref={cancelHref} error={error} isLoading={isLoading} + reviewTaskType={reviewTaskType} /> ); diff --git a/src/components/Collaborative/Components/FloatingMenuContent.tsx b/src/components/Collaborative/Components/FloatingMenuContent.tsx index 1b0a7c501..16a2d2766 100644 --- a/src/components/Collaborative/Components/FloatingMenuContent.tsx +++ b/src/components/Collaborative/Components/FloatingMenuContent.tsx @@ -1,6 +1,7 @@ import React from "react"; import CommentContainer from "../Comment/CommentContainer"; import FloatingLinkToolbar from "./LinkToolBar/FloatingLinkToolbar"; +import { ReviewTaskTypeEnum } from "../../../machines/reviewTask/enums"; const FloatingMenuContent = ({ state, @@ -14,6 +15,7 @@ const FloatingMenuContent = ({ cancelHref, error, isLoading, + reviewTaskType, }) => { return ( <> @@ -22,16 +24,19 @@ const FloatingMenuContent = ({ isCommentVisible={isCommentVisible} setIsCommentVisible={setIsCommentVisible} /> - + + {reviewTaskType === ReviewTaskTypeEnum.Claim && ( + + )} ); }; diff --git a/src/components/Collaborative/utils/getEditorConfig.tsx b/src/components/Collaborative/utils/getEditorConfig.tsx index eebbdc2bb..d1e7bbdf4 100644 --- a/src/components/Collaborative/utils/getEditorConfig.tsx +++ b/src/components/Collaborative/utils/getEditorConfig.tsx @@ -19,9 +19,16 @@ export class EditorConfig { websocketProvider: any, enableEditorAnnotations: boolean ): Partial[] { - const baseExtensions: Partial[] = [ + const baseExtensions: Partial< + NodeExtension | PlainExtension | LinkExtension + >[] = [ new SummaryExtension({ disableExtraAttributes: true }), new TrailingNodeExtension(), + new LinkExtension({ + extraAttributes: { id: () => null }, + autoLink: type === ReviewTaskTypeEnum.Claim, + selectTextOnClick: true, + }), ]; if (websocketProvider) { @@ -41,11 +48,6 @@ export class EditorConfig { case ReviewTaskTypeEnum.Claim: return [ ...baseExtensions, - new LinkExtension({ - extraAttributes: { id: () => null }, - autoLink: true, - selectTextOnClick: true, - }), new QuestionExtension({ disableExtraAttributes: true }), new ReportExtension({ disableExtraAttributes: true }), new VerificationExtension({ disableExtraAttributes: true }),