diff --git a/src/ui/pages/container/Label-Studio/AllTaskLSF.jsx b/src/ui/pages/container/Label-Studio/AllTaskLSF.jsx index a1208ef24..6fdef02b4 100644 --- a/src/ui/pages/container/Label-Studio/AllTaskLSF.jsx +++ b/src/ui/pages/container/Label-Studio/AllTaskLSF.jsx @@ -26,7 +26,7 @@ import APITransport from '../../../../redux/actions/apitransport/apitransport'; import { useParams, useNavigate } from "react-router-dom"; import useFullPageLoader from "../../../../hooks/useFullPageLoader"; import { snakeToTitleCase } from '../../../../utils/utils'; - +import keymap from './keymap'; import styles from './lsf.module.css' import "./lsf.css" import { useDispatch, useSelector } from 'react-redux'; @@ -205,6 +205,7 @@ useEffect(() => { id: taskData.id, data: taskData.data, }, + keymap: keymap, onLabelStudioLoad: function (ls) { annotation_status.current = ProjectDetails.project_stage == 2 ? "labeled": "accepted"; diff --git a/src/ui/pages/container/Label-Studio/LSF.jsx b/src/ui/pages/container/Label-Studio/LSF.jsx index 9af60fd7e..e961bde08 100644 --- a/src/ui/pages/container/Label-Studio/LSF.jsx +++ b/src/ui/pages/container/Label-Studio/LSF.jsx @@ -1,8 +1,8 @@ import PropTypes from "prop-types"; import React, { useState, useEffect, useRef } from "react"; -import ReactQuill, { Quill } from 'react-quill'; -import "./editor.css" -import 'quill/dist/quill.snow.css'; +import ReactQuill, { Quill } from "react-quill"; +import "./editor.css"; +import "quill/dist/quill.snow.css"; import LabelStudio from "@heartexlabs/label-studio"; import { Tooltip, @@ -24,6 +24,8 @@ import ArrowRightIcon from "@mui/icons-material/ArrowRight"; import CustomizedSnackbars from "../../component/common/Snackbar"; import generateLabelConfig from "../../../../utils/LabelConfig/ConversationTranslation"; import conversationVerificationLabelConfig from "../../../../utils/LabelConfig/ConversationVerification"; +// import keymap from "@label-studio/keymap"; +import keymap from "./keymap"; import { getProjectsandTasks, @@ -46,7 +48,7 @@ import Glossary from "../Glossary/Glossary"; import { TabsSuggestionData } from "../../../../utils/TabsSuggestionData/TabsSuggestionData"; import InfoIcon from "@mui/icons-material/Info"; import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; -import getTaskAssignedUsers from '../../../../utils/getTaskAssignedUsers'; +import getTaskAssignedUsers from "../../../../utils/getTaskAssignedUsers"; import LightTooltip from "../../component/common/Tooltip"; import { labelConfigJS } from "./labelConfigJSX"; @@ -64,12 +66,10 @@ const filterAnnotations = ( return annotation.completed_by === user.id && !annotation.parent_annotation; }); let userAnnotationData = annotations.find( - (annotation) => - annotation.annotation_type === 2 + (annotation) => annotation.annotation_type === 2 ); if (userAnnotation) { - if (userAnnotation.annotation_status === "labeled") { const superCheckedAnnotation = annotations.find( (annotation) => annotation.annotation_type === 3 @@ -93,12 +93,9 @@ const filterAnnotations = ( disable = true; } else if ( review && - [ - "skipped", - "draft", - "rejected", - "unreviewed", - ].includes(review.annotation_status) + ["skipped", "draft", "rejected", "unreviewed"].includes( + review.annotation_status + ) ) { filteredAnnotations = [userAnnotation]; disable = true; @@ -119,31 +116,27 @@ const filterAnnotations = ( } else { filteredAnnotations = [userAnnotation]; } - } - else if ( + } else if ( userAnnotationData && - [ - "draft", - ].includes(userAnnotation.annotation_status) + ["draft"].includes(userAnnotation.annotation_status) ) { filteredAnnotations = [userAnnotation]; disableSkip = true; setDisableButton(true); - setFilterMessage("Skip button is disabled, since the task is being reviewed"); - } - else if ( + setFilterMessage( + "Skip button is disabled, since the task is being reviewed" + ); + } else if ( userAnnotation && - [ - "to_be_revised" - ].includes(userAnnotation.annotation_status) + ["to_be_revised"].includes(userAnnotation.annotation_status) ) { filteredAnnotations = [userAnnotation]; disableSkip = true; setDisableButton(true); - setFilterMessage("Skip button is disabled, since the task is being reviewed"); - } - - else { + setFilterMessage( + "Skip button is disabled, since the task is being reviewed" + ); + } else { filteredAnnotations = [userAnnotation]; } } else if ([4, 5, 6].includes(user.role)) { @@ -161,7 +154,7 @@ const AUTO_SAVE_INTERVAL = 30000; //1 minute const AUDIO_PROJECT_SAVE_CHECK = [ "AudioTranscription", "AudioTranscriptionEditing", - "AcousticNormalisedTranscriptionEditing" + "AcousticNormalisedTranscriptionEditing", ]; const LabelStudioWrapper = ({ @@ -208,14 +201,14 @@ const LabelStudioWrapper = ({ //console.log("projectId, taskId", projectId, taskId); // debugger // const projectType = ProjectDetails?.project_type?.includes("Audio") - + /* useEffect(() => { if(Object.keys(userData).includes("prefer_cl_ui") && (userData.prefer_cl_ui) && ProjectDetails?.project_type?.includes("Acoustic")) { autoSaveAnnotation(); navigate(`/projects/${projectId}/AudioTranscriptionLandingPage/${taskId}`); } }, [userData]); */ - + useEffect(() => { let sidePanel = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); let showLabelsOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); @@ -279,13 +272,14 @@ const LabelStudioWrapper = ({ let interfaces = []; if (predictions == null) predictions = []; - const [filteredAnnotations, disableLSFControls, disableSkip] = filterAnnotations( - annotations, - userData, - setDisableBtns, - setFilterMessage, - setDisableButton - ); + const [filteredAnnotations, disableLSFControls, disableSkip] = + filterAnnotations( + annotations, + userData, + setDisableBtns, + setFilterMessage, + setDisableButton + ); isAudioProject.current = AUDIO_PROJECT_SAVE_CHECK.includes(projectType); //console.log("labelConfig", labelConfig); @@ -299,7 +293,9 @@ const LabelStudioWrapper = ({ "infobar", "topbar", "instruction", - ...(isAudioProject.current || projectType.includes("OCR") ? ["side-column"] : []), + ...(isAudioProject.current || projectType.includes("OCR") + ? ["side-column"] + : []), "annotations:history", "annotations:tabs", "annotations:menu", @@ -326,7 +322,9 @@ const LabelStudioWrapper = ({ "infobar", "topbar", "instruction", - ...(isAudioProject.current || projectType.includes("OCR") ? ["side-column"] : []), + ...(isAudioProject.current || projectType.includes("OCR") + ? ["side-column"] + : []), "annotations:history", "annotations:tabs", "annotations:menu", @@ -340,8 +338,11 @@ const LabelStudioWrapper = ({ "edit-history", ]; } - if (disableLSFControls || !taskData?.annotation_users?.some( - (user) => user === userData.id)) setAutoSave(false); + if ( + disableLSFControls || + !taskData?.annotation_users?.some((user) => user === userData.id) + ) + setAutoSave(false); if (rootRef.current) { if (lsfRef.current) { @@ -365,6 +366,7 @@ const LabelStudioWrapper = ({ id: taskData.id, data: taskData.data, }, + keymap: keymap, onLabelStudioLoad: function (ls) { annotation_status.current = @@ -391,14 +393,13 @@ const LabelStudioWrapper = ({ countLables++; } }); - if (projectType.includes("OCR") && ids.size>countLables) { + if (projectType.includes("OCR") && ids.size > countLables) { setSnackbarInfo({ open: true, message: "Please select labels for all boxes", variant: "error", }); - } - else { + } else { if (isAudioProject.current) { const counter = temp.reduce((acc, curr) => { if (curr.from_name === "labels") @@ -417,7 +418,8 @@ const LabelStudioWrapper = ({ if (counter.labels !== counter.textareas || counter.empty) { setSnackbarInfo({ open: true, - message: "Please fill the annotations for every segment/region", + message: + "Please fill the annotations for every segment/region", variant: "warning", }); return; @@ -432,7 +434,9 @@ const LabelStudioWrapper = ({ load_time.current, annotation.lead_time, annotation_status.current, - JSON.stringify(annotationNotesRef.current.getEditor().getContents()) + JSON.stringify( + annotationNotesRef.current.getEditor().getContents() + ) ).then((res) => { if (localStorage.getItem("labelAll")) getNextProject(projectId, taskData.id).then((res) => { @@ -468,7 +472,9 @@ const LabelStudioWrapper = ({ load_time.current, annotation.lead_time, "skipped", - JSON.stringify(annotationNotesRef.current.getEditor().getContents()) + JSON.stringify( + annotationNotesRef.current.getEditor().getContents() + ) ).then(() => { getNextProject(projectId, taskData.id).then((res) => { hideLoader(); @@ -481,7 +487,7 @@ const LabelStudioWrapper = ({ onUpdateAnnotation: function (ls, annotation) { let temp = annotation.serializeAnnotation(); let ids = new Set(); - let countLables = 0; + let countLables = 0; temp.map((curr) => { // console.log(curr); if(curr.type !== "relation"){ @@ -491,14 +497,13 @@ const LabelStudioWrapper = ({ countLables++; } }); - if (projectType.includes("OCR") && ids.size>countLables) { + if (projectType.includes("OCR") && ids.size > countLables) { setSnackbarInfo({ open: true, message: "Please select labels for all boxes", variant: "error", }); - } - else { + } else { if (isAudioProject.current) { const counter = temp.reduce((acc, curr) => { if (curr.from_name === "labels") @@ -516,7 +521,8 @@ const LabelStudioWrapper = ({ if (counter.labels !== counter.textareas || counter.empty) { setSnackbarInfo({ open: true, - message: "Please fill the annotations for every segment/region", + message: + "Please fill the annotations for every segment/region", variant: "warning", }); return; @@ -525,9 +531,10 @@ const LabelStudioWrapper = ({ if (taskData.annotation_status !== "freezed") { for (let i = 0; i < annotations.length; i++) { if ( - !annotations[i].result?.length || !annotation.serializeAnnotation().length || + !annotations[i].result?.length || + !annotation.serializeAnnotation().length || annotation.serializeAnnotation()[0].id === - annotations[i].result[0].id + annotations[i].result[0].id ) { setAutoSave(false); showLoader(); @@ -546,7 +553,9 @@ const LabelStudioWrapper = ({ load_time.current, annotations[i].lead_time, annotation_status.current, - JSON.stringify(annotationNotesRef.current.getEditor().getContents()) + JSON.stringify( + annotationNotesRef.current.getEditor().getContents() + ) ).then((res) => { hideLoader(); if (res.status !== 200) { @@ -555,8 +564,7 @@ const LabelStudioWrapper = ({ message: "Error in saving annotation", variant: "error", }); - } - else if (localStorage.getItem("labelAll")) + } else if (localStorage.getItem("labelAll")) getNextProject(projectId, taskData.id).then((res) => { tasksComplete(res?.id || null); }); @@ -609,8 +617,12 @@ const LabelStudioWrapper = ({ loaded.current = taskId; getProjectsandTasks(projectId, taskId).then( ([labelConfig, taskData, annotations, predictions]) => { - if (annotations.message?.includes("not a part of this project") || annotations.detail?.includes("Not found")) { - if (annotations.detail?.includes("Not found")) annotations.message = "Task not found"; + if ( + annotations.message?.includes("not a part of this project") || + annotations.detail?.includes("Not found") + ) { + if (annotations.detail?.includes("Not found")) + annotations.message = "Task not found"; setSnackbarInfo({ open: true, message: annotations.message, @@ -621,8 +633,14 @@ const LabelStudioWrapper = ({ } // both have loaded! // console.log("[labelConfig, taskData, annotations, predictions]", [labelConfig, taskData, annotations, predictions]); - let tempLabelConfig = labelConfig.project_type === "ConversationTranslation" || labelConfig.project_type === "ConversationTranslationEditing" ? generateLabelConfig(taskData.data) : labelConfig.project_type === "ConversationVerification" ? conversationVerificationLabelConfig(taskData.data) : labelConfig.label_config; - if (labelConfig.project_type.includes("OCRSegmentCategorization")){ + let tempLabelConfig = + labelConfig.project_type === "ConversationTranslation" || + labelConfig.project_type === "ConversationTranslationEditing" + ? generateLabelConfig(taskData.data) + : labelConfig.project_type === "ConversationVerification" + ? conversationVerificationLabelConfig(taskData.data) + : labelConfig.label_config; + if (labelConfig.project_type.includes("OCRSegmentCategorization")) { tempLabelConfig = labelConfigJS; } setAnnotations(annotations); @@ -771,22 +789,27 @@ const LabelStudioWrapper = ({ useEffect(() => { const showAssignedUsers = async () => { - getTaskAssignedUsers(taskData).then(res => setAssignedUsers(res)); - } + getTaskAssignedUsers(taskData).then((res) => setAssignedUsers(res)); + }; taskData?.id && showAssignedUsers(); }, [taskData]); const autoSaveAnnotation = () => { - if (autoSave && lsfRef.current?.store?.annotationStore?.selected && taskData.task_status.toLowerCase() !== "labeled") { + if ( + autoSave && + lsfRef.current?.store?.annotationStore?.selected && + taskData.task_status.toLowerCase() !== "labeled" + ) { if (taskData?.annotation_status !== "freezed") { let annotation = lsfRef.current.store.annotationStore.selected; + let temp; for (let i = 0; i < annotations.length; i++) { if ( !annotations[i].result?.length || annotation.serializeAnnotation()[0].id === - annotations[i].result[0].id + annotations[i].result[0].id ) { - let temp = annotation.serializeAnnotation(); + temp = annotation.serializeAnnotation(); if (annotations[i].annotation_type !== 1) continue; for (let i = 0; i < temp.length; i++) { if(temp[i].type === "relation"){ @@ -825,15 +848,15 @@ const LabelStudioWrapper = ({ }; let hidden, visibilityChange; - if (typeof document.hidden !== 'undefined') { - hidden = 'hidden'; - visibilityChange = 'visibilitychange'; - } else if (typeof document.msHidden !== 'undefined') { - hidden = 'msHidden'; - visibilityChange = 'msvisibilitychange'; - } else if (typeof document.webkitHidden !== 'undefined') { - hidden = 'webkitHidden'; - visibilityChange = 'webkitvisibilitychange'; + if (typeof document.hidden !== "undefined") { + hidden = "hidden"; + visibilityChange = "visibilitychange"; + } else if (typeof document.msHidden !== "undefined") { + hidden = "msHidden"; + visibilityChange = "msvisibilitychange"; + } else if (typeof document.webkitHidden !== "undefined") { + hidden = "webkitHidden"; + visibilityChange = "webkitvisibilitychange"; } const [visible, setVisibile] = useState(!document[hidden]); @@ -843,7 +866,7 @@ const LabelStudioWrapper = ({ document.addEventListener(visibilityChange, handleVisibilityChange); return () => { document.removeEventListener(visibilityChange, handleVisibilityChange); - } + }; }, []); useEffect(() => { @@ -855,7 +878,12 @@ const LabelStudioWrapper = ({ visible && autoSaveAnnotation(); }, AUTO_SAVE_INTERVAL); return () => clearInterval(interval); - }, [visible, autoSave, lsfRef.current?.store?.annotationStore?.selected, taskData]); + }, [ + visible, + autoSave, + lsfRef.current?.store?.annotationStore?.selected, + taskData, + ]); const handleDraftAnnotationClick = async () => { annotation_status.current = "draft"; @@ -885,14 +913,16 @@ const LabelStudioWrapper = ({ /> ); }; + return (