diff --git a/package-lock.json b/package-lock.json index 4e4bf71dd..edc1488d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "shoonya-new-frontend", "version": "0.1.0", "dependencies": { - "@ai4bharat/indic-transliterate": "^1.2.14", + "@ai4bharat/indic-transliterate": "github:AI4Bharat/indic-transliterate-js-new", "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", "@heartexlabs/label-studio": "^1.4.0", @@ -83,9 +83,9 @@ "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==" }, "node_modules/@ai4bharat/indic-transliterate": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@ai4bharat/indic-transliterate/-/indic-transliterate-1.2.15.tgz", - "integrity": "sha512-ErbTOPqg4EVSqiCpUACWbhw3LHjsd6IRxziTmp5h7HIArtQ5B4F9wVb9dTGUsjqZ9tgyZQBRQFmk3+CD53fRPA==", + "version": "1.2.14", + "resolved": "git+ssh://git@github.com/AI4Bharat/indic-transliterate-js-new.git#dfab0dd1dbd6588ddf1c867fc9a591f99ac9285e", + "license": "MIT", "dependencies": { "textarea-caret": "^3.1.0" }, diff --git a/package.json b/package.json index 23864c925..82e651806 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.1.0", "private": true, "dependencies": { - "@ai4bharat/indic-transliterate": "^1.2.14", + "@ai4bharat/indic-transliterate": "github:AI4Bharat/indic-transliterate-js-new", "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", "@heartexlabs/label-studio": "^1.4.0", diff --git a/src/IndicTransliterate/index.css b/src/IndicTransliterate/index.css new file mode 100644 index 000000000..da407d3af --- /dev/null +++ b/src/IndicTransliterate/index.css @@ -0,0 +1,31 @@ +._ReactTransliterate_1b0d4b { + background-clip: padding-box; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.15); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + display: block; + font-size: 14px; + list-style: none; + padding: 1px; + text-align: left; + z-index: 20000; + width: 100%; +} + +._ReactTransliterate_1b0d4b > li { + cursor: pointer; + padding: 10px; + min-width: 100px; + background-color: #fff; +} + +._ReactTransliterate_1b0d4b > li:hover { + background-color: red !important; +} + +._Active_1b0d4b { + background-color: red!important; + color: yellow; +} + +/*# sourceMappingURL=index.css.map */ diff --git a/src/config/dropDownValues.js b/src/config/dropDownValues.js index 069fe1b98..5f8f5e8fe 100644 --- a/src/config/dropDownValues.js +++ b/src/config/dropDownValues.js @@ -1 +1 @@ -export const participationType = ["FULL_TIME", "PART_TIME", "NA"]; +export const participationType = ["FULL_TIME", "PART_TIME", "NA", "CONTRACT_BASIS"]; diff --git a/src/redux/actions/api/ProjectDetails/DeallocationAnnotatorsAndReviewers.js b/src/redux/actions/api/ProjectDetails/DeallocationAnnotatorsAndReviewers.js index 3f7893d6d..948ee2755 100644 --- a/src/redux/actions/api/ProjectDetails/DeallocationAnnotatorsAndReviewers.js +++ b/src/redux/actions/api/ProjectDetails/DeallocationAnnotatorsAndReviewers.js @@ -1,42 +1,88 @@ import API from "../../../api"; import ENDPOINTS from "../../../../config/apiendpoint"; import constants from "../../../constants"; - - export default class DeallocationAnnotatorsAndReviewersAPI extends API { - constructor(projectId,radiobutton,annotatorsUser,reviewerssUser,annotationStatus,reviewStatus,superCheckUser,SuperCheckStatus,projectObj, timeout = 2000) { - super("GET", timeout, false); - this.projectObj = projectObj; - const queryString = radiobutton === "annotation" ? `unassign_tasks/?annotator_id=${annotatorsUser}&annotation_status=["${annotationStatus}"]` : radiobutton === "review"? `unassign_review_tasks/?reviewer_id=${reviewerssUser}&review_status=["${reviewStatus}"]`:`unassign_supercheck_tasks/?superchecker_id=${superCheckUser}&supercheck_status=["${SuperCheckStatus}"]`; - console.log(queryString,"queryStringqueryString") - this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getProjects}${projectId}/${queryString}`; - } - - processResponse(res) { - super.processResponse(res); - if (res) { - this.deallocationAnnotatorsAndReviewers= res; - } - } - - apiEndPoint() { - return this.endpoint; - } - getBody() { - return this.projectObj; - } - - getHeaders() { - this.headers = { - headers: { - "Content-Type": "application/json", - "Authorization":`JWT ${localStorage.getItem('shoonya_access_token')}` - }, - }; - return this.headers; - } - - getPayload() { - return this.deallocationAnnotatorsAndReviewers - } + +export class DeallocateTaskById extends API { + constructor(projectId, taskId, selectedUser, timeout = 2000) { + super("POST", timeout, false); + this.projectId = projectId; + + this.payload = { + task_ids: Array.isArray(taskId) ? taskId.map(id => parseInt(id)) : [parseInt(taskId)], + }; + const baseEndpoint = `${super.apiEndPointAuto()}/${ENDPOINTS.getProjects}${projectId}/`; + + const endpointMap = { + annotation: 'unassign_tasks/', + review: `unassign_review_tasks/`, + superChecker: 'unassign_supercheck_task/', + }; + + const selectedUserEndpoint = endpointMap[selectedUser]; + + if (selectedUserEndpoint) { + this.endpoint = baseEndpoint + selectedUserEndpoint; + } else { + console.error('Invalid selectedUser:', selectedUser); + } + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.deallocateTaskById = res; + } + } + apiEndPoint() { + return this.endpoint; + } + getBody() { + return this.payload; + } + getHeaders() { + return { + "Content-Type": "application/json", + Authorization: `JWT ${localStorage.getItem("shoonya_access_token")}`, + }; + } + getPayload() { + return this.deallocateTaskById; + } +} + +export default class DeallocationAnnotatorsAndReviewersAPI extends API { + constructor(projectId,radiobutton,annotatorsUser,reviewerssUser,annotationStatus,reviewStatus,superCheckUser,SuperCheckStatus,projectObj, timeout = 2000) { + super("POST", timeout, false); + this.projectObj = projectObj; + const queryString = radiobutton === "annotation" ? `unassign_tasks/?annotator_id=${annotatorsUser}&annotation_status=["${annotationStatus}"]` : radiobutton === "review"? `unassign_review_tasks/?reviewer_id=${reviewerssUser}&review_status=["${reviewStatus}"]`:`unassign_supercheck_tasks/?superchecker_id=${superCheckUser}&supercheck_status=["${SuperCheckStatus}"]`; + this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getProjects}${projectId}/${queryString}`; + } + + processResponse(res) { + super.processResponse(res); + if (res) { + this.deallocationAnnotatorsAndReviewers= res; + } +} + + apiEndPoint() { + return this.endpoint; + } + getBody() { + return this.projectObj; } - \ No newline at end of file + + getHeaders() { + this.headers = { + headers: { + "Content-Type": "application/json", + "Authorization":`JWT ${localStorage.getItem('shoonya_access_token')}` + }, + }; + return this.headers; + } + + getPayload() { + return this.deallocationAnnotatorsAndReviewers + } +} diff --git a/src/redux/actions/api/Tasks/DeAllocateSuperCheckerTasks.js b/src/redux/actions/api/Tasks/DeAllocateSuperCheckerTasks.js index caf5fde83..abf10daa6 100644 --- a/src/redux/actions/api/Tasks/DeAllocateSuperCheckerTasks.js +++ b/src/redux/actions/api/Tasks/DeAllocateSuperCheckerTasks.js @@ -8,7 +8,7 @@ import constants from "../../../constants"; export default class DeallocateSuperCheckerTasksAPI extends API { constructor(projectId,selectedFilters, timeout = 2000) { - super("GET", timeout, false); + super("POST", timeout, false); this.projectId = projectId; this.type = constants.DE_ALLOCATE_SUPERCHECKER_TASKS; this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getProjects}${projectId}/unassign_supercheck_tasks/?supercheck_status=['${selectedFilters}']`; diff --git a/src/redux/actions/api/Tasks/DeallocateReviewTasks.js b/src/redux/actions/api/Tasks/DeallocateReviewTasks.js index f05512122..9783cad02 100644 --- a/src/redux/actions/api/Tasks/DeallocateReviewTasks.js +++ b/src/redux/actions/api/Tasks/DeallocateReviewTasks.js @@ -8,7 +8,7 @@ export default class DeallocateReviewTasksAPI extends API { constructor(projectId,selectedFilters, timeout = 2000) { - super("GET", timeout, false); + super("POST", timeout, false); this.projectId = projectId; this.type = constants.DE_ALLOCATE_REVIEW_TASKS; this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getProjects}${projectId}/unassign_review_tasks/?review_status=['${selectedFilters}']`; diff --git a/src/redux/actions/api/Tasks/DeallocateTasks.js b/src/redux/actions/api/Tasks/DeallocateTasks.js index 38c8c8cbd..eafbcd6fe 100644 --- a/src/redux/actions/api/Tasks/DeallocateTasks.js +++ b/src/redux/actions/api/Tasks/DeallocateTasks.js @@ -7,7 +7,7 @@ export default class DeallocateTasksAPI extends API { constructor(projectId,selectedFilters, timeout = 2000) { - super("GET", timeout, false); + super("POST", timeout, false); this.projectId = projectId; this.type = constants.DE_ALLOCATE_TASKS; this.endpoint = `${super.apiEndPointAuto()}${ENDPOINTS.getProjects}${projectId}/unassign_tasks/?annotation_status=['${selectedFilters}']`; diff --git a/src/ui/pages/component/CL-Transcription/SettingsButtonComponent.jsx b/src/ui/pages/component/CL-Transcription/SettingsButtonComponent.jsx index bc9a8f82d..bcb865652 100644 --- a/src/ui/pages/component/CL-Transcription/SettingsButtonComponent.jsx +++ b/src/ui/pages/component/CL-Transcription/SettingsButtonComponent.jsx @@ -141,6 +141,7 @@ const SettingsButtonComponent = ({ checked={enableTransliteration} onChange={() => { setAnchorElSettings(null); + localStorage.setItem("userCustomTranscriptionSettings",JSON.stringify({...JSON.parse(localStorage.getItem("userCustomTranscriptionSettings")),"enableTransliteration":!enableTransliteration})) setTransliteration(!enableTransliteration); }} /> @@ -155,6 +156,7 @@ const SettingsButtonComponent = ({ checked={enableRTL_Typing} onChange={() => { setAnchorElSettings(null); + localStorage.setItem("userCustomTranscriptionSettings",JSON.stringify({...JSON.parse(localStorage.getItem("userCustomTranscriptionSettings")),"enableRTL_Typing":!enableRTL_Typing})) setRTL_Typing(!enableRTL_Typing); }} /> @@ -297,6 +299,7 @@ const SettingsButtonComponent = ({ { + localStorage.setItem("userCustomTranscriptionSettings",JSON.stringify({...JSON.parse(localStorage.getItem("userCustomTranscriptionSettings")),"fontSize":item.size})) setFontSize(item.size); }} > diff --git a/src/ui/pages/component/Project/TaskTable.jsx b/src/ui/pages/component/Project/TaskTable.jsx index 8f9675e66..1a604cc6b 100644 --- a/src/ui/pages/component/Project/TaskTable.jsx +++ b/src/ui/pages/component/Project/TaskTable.jsx @@ -246,7 +246,7 @@ const TaskTable = (props) => { ? new DeallocateTasksAPI(id, selectedFilters.annotation_status) : new DeallocateReviewTasksAPI(id, selectedFilters.review_status); const res = await fetch(deallocateObj.apiEndPoint(), { - method: "GET", + method: "POST", body: JSON.stringify(deallocateObj.getBody()), headers: deallocateObj.getHeaders().headers, }); diff --git a/src/ui/pages/component/Tabs/AdvancedOperation.jsx b/src/ui/pages/component/Tabs/AdvancedOperation.jsx index 750fad536..0915576dd 100644 --- a/src/ui/pages/component/Tabs/AdvancedOperation.jsx +++ b/src/ui/pages/component/Tabs/AdvancedOperation.jsx @@ -759,4 +759,4 @@ const AdvancedOperation = (props) => { ); }; -export default AdvancedOperation; +export default AdvancedOperation; \ No newline at end of file diff --git a/src/ui/pages/component/Tabs/MyProgress.jsx b/src/ui/pages/component/Tabs/MyProgress.jsx index b94637d77..df25c8191 100644 --- a/src/ui/pages/component/Tabs/MyProgress.jsx +++ b/src/ui/pages/component/Tabs/MyProgress.jsx @@ -354,7 +354,7 @@ const MyProgress = () => { { label: "Till Date", range: () => ({ - startDate: new Date(Date.parse(UserDetails?.date_joined, 'yyyy-MM-ddTHH:mm:ss.SSSZ')), + startDate: new Date('2021-01-01'), endDate: new Date(), }), isSelected(range) { @@ -370,7 +370,7 @@ const MyProgress = () => { moveRangeOnFirstSelection={false} months={2} ranges={selectRange} - minDate={new Date(Date.parse(UserDetails?.date_joined, 'yyyy-MM-ddTHH:mm:ss.SSSZ'))} + minDate={new Date('2021-01-01')} maxDate={new Date()} direction="horizontal" /> diff --git a/src/ui/pages/component/common/DataitemsTable.jsx b/src/ui/pages/component/common/DataitemsTable.jsx index 3e10a06fd..f97461084 100644 --- a/src/ui/pages/component/common/DataitemsTable.jsx +++ b/src/ui/pages/component/common/DataitemsTable.jsx @@ -102,7 +102,7 @@ useEffect(() => { align: "center", customHeadLabelRender: customColumnHead, customBodyRender: (value) => { - if ((key == "metadata_json" || key == "prediction_json"|| key == "ocr_prediction_json"|| key == "transcribed_json"|| key == "draft_data_json" || key == "ocr_transcribed_json") && value !== null ) { + if ((key == "metadata_json" || key == "prediction_json"|| key == "ocr_prediction_json"|| key == "transcribed_json"|| key == "draft_data_json" || key == "ocr_transcribed_json" || key == "bboxes_relation_json") && value !== null ) { const data = JSON.stringify(value) const metadata = data.replace(/\\/g, ""); return metadata; diff --git a/src/ui/pages/component/common/Header.jsx b/src/ui/pages/component/common/Header.jsx index 9a4853bd8..e2553df5e 100644 --- a/src/ui/pages/component/common/Header.jsx +++ b/src/ui/pages/component/common/Header.jsx @@ -75,6 +75,10 @@ const Header = () => { //const[checkClUI,setCheckClUI]=useState(null) const [moreHorizonAnchorEl, setMoreHorizonAnchorEl] = useState(null); + if(localStorage.getItem("source") !== undefined){ + localStorage.setItem("source", "shoonya-frontend"); + } + const handleMoreHorizonClick = (event) => { setMoreHorizonAnchorEl(event.currentTarget); }; diff --git a/src/ui/pages/container/CL-Transcription/AudioTranscriptionLandingPage.jsx b/src/ui/pages/container/CL-Transcription/AudioTranscriptionLandingPage.jsx index 2a416fc58..ba322f629 100644 --- a/src/ui/pages/container/CL-Transcription/AudioTranscriptionLandingPage.jsx +++ b/src/ui/pages/container/CL-Transcription/AudioTranscriptionLandingPage.jsx @@ -110,8 +110,8 @@ const AudioTranscriptionLandingPage = () => { const [advancedWaveformSettings, setAdvancedWaveformSettings] = useState(false); const [assignedUsers, setAssignedUsers] = useState(null); const [autoSave, setAutoSave] = useState(true); - const [autoSaveTrigger, setAutoSaveTrigger] = useState(false); const [waveSurfer, setWaveSurfer] = useState(true); + const [autoSaveTrigger, setAutoSaveTrigger] = useState(false); // useEffect(() => { // let intervalId; diff --git a/src/ui/pages/container/CL-Transcription/ReviewAudioTranscriptionLandingPage.jsx b/src/ui/pages/container/CL-Transcription/ReviewAudioTranscriptionLandingPage.jsx index 6d28ee639..8a4e105fa 100644 --- a/src/ui/pages/container/CL-Transcription/ReviewAudioTranscriptionLandingPage.jsx +++ b/src/ui/pages/container/CL-Transcription/ReviewAudioTranscriptionLandingPage.jsx @@ -114,8 +114,8 @@ const ReviewAudioTranscriptionLandingPage = () => { const [advancedWaveformSettings, setAdvancedWaveformSettings] = useState(false); const [assignedUsers, setAssignedUsers] = useState(null); const [autoSave, setAutoSave] = useState(true); - const [autoSaveTrigger, setAutoSaveTrigger] = useState(false); const [waveSurfer, setWaveSurfer] = useState(true); + const [autoSaveTrigger, setAutoSaveTrigger] = useState(false); // useEffect(() => { // let intervalId; @@ -304,11 +304,11 @@ const ReviewAudioTranscriptionLandingPage = () => { variant: "error", }); }else{setTaskDetailList(resp); - if (resp?.data?.audio_duration < 700){ - setWaveSurfer(false); - }else{ - setWaveSurfer(true); - }} + if (resp?.data?.audio_duration < 700){ + setWaveSurfer(false); + }else{ + setWaveSurfer(true); + }} setLoading(false); }; diff --git a/src/ui/pages/container/CL-Transcription/SuperCheckerAudioTranscriptionLandingPage.jsx b/src/ui/pages/container/CL-Transcription/SuperCheckerAudioTranscriptionLandingPage.jsx index 4e2947982..d00ca2b47 100644 --- a/src/ui/pages/container/CL-Transcription/SuperCheckerAudioTranscriptionLandingPage.jsx +++ b/src/ui/pages/container/CL-Transcription/SuperCheckerAudioTranscriptionLandingPage.jsx @@ -112,8 +112,8 @@ const SuperCheckerAudioTranscriptionLandingPage = () => { const [advancedWaveformSettings, setAdvancedWaveformSettings] = useState(false); const [assignedUsers, setAssignedUsers] = useState(null); const [autoSave, setAutoSave] = useState(true); + const [waveSurfer, setWaveSurfer] = useState(false); const [autoSaveTrigger, setAutoSaveTrigger] = useState(false); - const [waveSurfer, setWaveSurfer] = useState(true); // useEffect(() => { // let intervalId; @@ -1142,6 +1142,7 @@ useEffect(() => { /> )} + /> ) : (
@@ -1253,4 +1254,4 @@ useEffect(() => { ); }; -export default SuperCheckerAudioTranscriptionLandingPage; +export default SuperCheckerAudioTranscriptionLandingPage; \ No newline at end of file diff --git a/src/ui/pages/container/CL-Transcription/TranscriptionRightPanel.jsx b/src/ui/pages/container/CL-Transcription/TranscriptionRightPanel.jsx index 02476cc70..487cc94ed 100644 --- a/src/ui/pages/container/CL-Transcription/TranscriptionRightPanel.jsx +++ b/src/ui/pages/container/CL-Transcription/TranscriptionRightPanel.jsx @@ -71,6 +71,7 @@ import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined'; // } from "redux/actions"; import { IconButton, Tooltip } from "@mui/material"; import { Add, MoreVert, Remove } from "@material-ui/icons"; +import TransliterationAPI from "../../../../redux/actions/api/Transliteration/TransliterationAPI"; const TranscriptionRightPanel = ({ currentIndex, @@ -86,6 +87,7 @@ const TranscriptionRightPanel = ({ annotationId, }) => { const { taskId } = useParams(); + const classes = AudioTranscriptionLandingStyle(); const navigate = useNavigate(); const dispatch = useDispatch(); @@ -123,11 +125,11 @@ const TranscriptionRightPanel = ({ const [selectionStart, setSelectionStart] = useState(); const [currentIndexToSplitTextBlock, setCurrentIndexToSplitTextBlock] = useState(); - const [enableTransliteration, setTransliteration] = useState(false); - const [enableRTL_Typing, setRTL_Typing] = useState(false); + const [enableTransliteration, setTransliteration] = useState(JSON.parse(localStorage.getItem("userCustomTranscriptionSettings"))?.enableTransliteration || false); + const [enableRTL_Typing, setRTL_Typing] = useState(JSON.parse(localStorage.getItem("userCustomTranscriptionSettings"))?.enableRTL_Typing || false); const [openConfirmDialog, setOpenConfirmDialog] = useState(false); const [loading, setLoading] = useState(false); - const [fontSize, setFontSize] = useState("large"); + const [fontSize, setFontSize] = useState(JSON.parse(localStorage.getItem("userCustomTranscriptionSettings"))?.fontSize || "large"); const [currentOffset, setCurrentOffset] = useState(1); const [undoStack, setUndoStack] = useState([]); const [redoStack, setRedoStack] = useState([]); @@ -222,6 +224,7 @@ const TranscriptionRightPanel = ({ const handleKeyDown = (event) => { if (event.altKey && event.key === "1") { event.preventDefault(); + localStorage.setItem("userCustomTranscriptionSettings",JSON.stringify({...JSON.parse(localStorage.getItem("userCustomTranscriptionSettings")),"enableTransliteration":!enableTransliteration})) setTransliteration(!enableTransliteration); } }; @@ -777,6 +780,7 @@ const TranscriptionRightPanel = ({ */}
)}} + /> ) : (
@@ -829,6 +833,7 @@ const TranscriptionRightPanel = ({ />
)}} + /> ) : (
diff --git a/src/ui/pages/container/CL-Transcription/wavesurfer.jsx b/src/ui/pages/container/CL-Transcription/wavesurfer.jsx index 4e0ddbcf7..2b4979dbc 100644 --- a/src/ui/pages/container/CL-Transcription/wavesurfer.jsx +++ b/src/ui/pages/container/CL-Transcription/wavesurfer.jsx @@ -8,7 +8,6 @@ import C from "../../../../redux/constants"; import DT from "duration-time-conversion"; const Timeline2 = ({ key, details, waveformSettings }) => { - console.log(key); const waveSurf = useRef(null); const miniMap = useRef(null); const regions = useRef(null); diff --git a/src/ui/pages/container/Glossary/AddGlossary.jsx b/src/ui/pages/container/Glossary/AddGlossary.jsx index ea16676fc..5fa3764bf 100644 --- a/src/ui/pages/container/Glossary/AddGlossary.jsx +++ b/src/ui/pages/container/Glossary/AddGlossary.jsx @@ -26,7 +26,7 @@ import { IndicTransliterate, getTransliterationLanguages, } from "@ai4bharat/indic-transliterate"; -import "@ai4bharat/indic-transliterate/dist/index.css"; +import "../../../../IndicTransliterate/index.css"; import { MenuProps } from "../../../../utils/utils"; const AddGlossary = ({ @@ -284,8 +284,7 @@ const AddGlossary = ({ setSourceText(SourceText); }} renderComponent={(props) => renderSourceText(props)} - - + />): ( renderTargetText(props)} + />): ( renderTargetText(props)} + />): ( { +useEffect(() => { let sidePanel = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); - localStorage.setItem("labelStudio:settings", JSON.stringify({ - bottomSidePanel: !sidePanel, - continuousLabeling: false, - enableAutoSave: false, - enableHotkeys: true, - enableLabelTooltips: true, - enablePanelHotkeys: true, - enableTooltips: false, - fullscreen: false, - imageFullSize: false, - selectAfterCreate: false, - showAnnotationsPanel: true, - showLabels: false, - showLineNumbers: false, - showPredictionsPanel: true, - sidePanelMode: "SIDEPANEL_MODE_REGIONS" - })) - }, []) + let showLabelsOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + let selectAfterCreateOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + let continousLabelingOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + localStorage.setItem( + "labelStudio:settings", + JSON.stringify({ + bottomSidePanel: !sidePanel, + continuousLabeling: continousLabelingOnly, + enableAutoSave: false, + enableHotkeys: true, + enableLabelTooltips: true, + enablePanelHotkeys: true, + enableTooltips: false, + fullscreen: false, + imageFullSize: false, + selectAfterCreate: selectAfterCreateOnly, + showAnnotationsPanel: true, + showLabels: showLabelsOnly, + showLineNumbers: false, + showPredictionsPanel: true, + sidePanelMode: "SIDEPANEL_MODE_REGIONS", + }) + ); + }, []); useEffect(() => { const showAssignedUsers = async () => { @@ -199,6 +205,7 @@ const LabelStudioWrapper = ({annotationNotesRef, loader, showLoader, hideLoader, id: taskData.id, data: taskData.data, }, + keymap: keymap, onLabelStudioLoad: function (ls) { annotation_status.current = ProjectDetails.project_stage == 2 ? "labeled": "accepted"; @@ -306,7 +313,9 @@ const LabelStudioWrapper = ({annotationNotesRef, loader, showLoader, hideLoader, showLoader(); for (let i = 0; i < temp.length; i++) { - if (temp[i].value.text) { + if(temp[i].type === "relation"){ + continue; + }else if (temp[i].value.text) { temp[i].value.text = [temp[i].value.text[0]] } } diff --git a/src/ui/pages/container/Label-Studio/LSF.jsx b/src/ui/pages/container/Label-Studio/LSF.jsx index c0b6e4142..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,21 +201,24 @@ 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"); + let selectAfterCreateOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + let continousLabelingOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); localStorage.setItem( "labelStudio:settings", JSON.stringify({ bottomSidePanel: !sidePanel, - continuousLabeling: false, + continuousLabeling: continousLabelingOnly, enableAutoSave: true, enableHotkeys: true, enableLabelTooltips: true, @@ -230,9 +226,9 @@ const LabelStudioWrapper = ({ enableTooltips: false, fullscreen: false, imageFullSize: false, - selectAfterCreate: false, + selectAfterCreate: selectAfterCreateOnly, showAnnotationsPanel: true, - showLabels: false, + showLabels: showLabelsOnly, showLineNumbers: false, showPredictionsPanel: true, sidePanelMode: "SIDEPANEL_MODE_REGIONS", @@ -276,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); @@ -296,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", @@ -323,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", @@ -337,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) { @@ -362,6 +366,7 @@ const LabelStudioWrapper = ({ id: taskData.id, data: taskData.data, }, + keymap: keymap, onLabelStudioLoad: function (ls) { annotation_status.current = @@ -381,28 +386,31 @@ const LabelStudioWrapper = ({ let ids = new Set(); let countLables = 0; temp.map((curr) => { - ids.add(curr.id); + if(curr.type !== "relation"){ + ids.add(curr.id); + } if(curr.type === "labels"){ 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") acc.labels++; else if (["transcribed_json", "verbatim_transcribed_json"].includes(curr.from_name)) { - if (curr.value.text[0] === "") + + if(curr.type !== "relation"){ + if (curr.value.text[0] === "") acc.empty++; acc.textareas++; - } + }} return acc; }, { labels: 0, textareas: 0, empty: 0 } @@ -410,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; @@ -425,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) => { @@ -461,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(); @@ -474,31 +487,33 @@ 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); - ids.add(curr.id); + // console.log(curr); + if(curr.type !== "relation"){ + ids.add(curr.id); + } if(curr.type === "labels"){ 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") acc.labels++; else if (["transcribed_json", "verbatim_transcribed_json"].includes(curr.from_name)) { - if (curr.value.text[0] === "") - acc.empty++; - acc.textareas++; - } + if(curr.type !== "relation"){ + if (curr.value.text[0] === "") + acc.empty++; + acc.textareas++; + }} return acc; }, { labels: 0, textareas: 0, empty: 0 } @@ -506,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; @@ -515,15 +531,18 @@ 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(); let temp = annotation.serializeAnnotation(); for (let i = 0; i < temp.length; i++) { - if (temp[i].value.text) { + if(temp[i].type === "relation"){ + continue; + }else if (temp[i].value.text) { temp[i].value.text = [temp[i].value.text[0]]; } } @@ -534,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) { @@ -543,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); }); @@ -597,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, @@ -609,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); @@ -759,25 +789,32 @@ 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].value.text) { + if(temp[i].type === "relation"){ + continue; + }else if (temp[i].value.text) { temp[i].value.text = [temp[i].value.text[0]]; } } @@ -811,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]); @@ -829,7 +866,7 @@ const LabelStudioWrapper = ({ document.addEventListener(visibilityChange, handleVisibilityChange); return () => { document.removeEventListener(visibilityChange, handleVisibilityChange); - } + }; }, []); useEffect(() => { @@ -841,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"; @@ -871,14 +913,16 @@ const LabelStudioWrapper = ({ /> ); }; + return (
- {autoSave && + {autoSave && (
Auto-save enabled for this scenario. -
} +
+ )} {filterMessage && ( {filterMessage} @@ -900,11 +944,15 @@ const LabelStudioWrapper = ({ minWidth: "40px", border: "1px solid #e6e6e6", color: "grey", - pt: 1, pl: 1, pr: 1, + pt: 1, + pl: 1, + pr: 1, borderBottom: "None", }} - > - + > + @@ -913,7 +961,7 @@ const LabelStudioWrapper = ({ {taskData?.annotation_users?.some( (user) => user === userData.id ) && - (!disableBtns) && ( + !disableBtns && ( @@ -1154,7 +1205,6 @@ export default function LSF() { style={{ display: showNotes ? "block" : "none", paddingBottom: "16px", - }} > {/* diff --git a/src/ui/pages/container/Label-Studio/ReviewLSF.jsx b/src/ui/pages/container/Label-Studio/ReviewLSF.jsx index ad9697bc6..bf79db791 100644 --- a/src/ui/pages/container/Label-Studio/ReviewLSF.jsx +++ b/src/ui/pages/container/Label-Studio/ReviewLSF.jsx @@ -35,6 +35,7 @@ import APITransport from "../../../../redux/actions/apitransport/apitransport"; import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; import getTaskAssignedUsers from '../../../../utils/getTaskAssignedUsers'; import LightTooltip from "../../component/common/Tooltip"; +import keymap from "./keymap"; import { getProjectsandTasks, @@ -268,13 +269,16 @@ const LabelStudioWrapper = ({ } }, [userData]); */ - useEffect(() => { +useEffect(() => { let sidePanel = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + let showLabelsOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + let selectAfterCreateOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + let continousLabelingOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); localStorage.setItem( "labelStudio:settings", JSON.stringify({ bottomSidePanel: !sidePanel, - continuousLabeling: false, + continuousLabeling: continousLabelingOnly, enableAutoSave: false, enableHotkeys: true, enableLabelTooltips: true, @@ -282,9 +286,9 @@ const LabelStudioWrapper = ({ enableTooltips: false, fullscreen: false, imageFullSize: false, - selectAfterCreate: false, + selectAfterCreate: selectAfterCreateOnly, showAnnotationsPanel: true, - showLabels: false, + showLabels: showLabelsOnly, showLineNumbers: false, showPredictionsPanel: true, sidePanelMode: "SIDEPANEL_MODE_REGIONS", @@ -417,6 +421,7 @@ const LabelStudioWrapper = ({ id: taskData.id, data: taskData.data, }, + keymap: keymap, onLabelStudioLoad: function (ls) { // if (taskData.correct_annotation) { @@ -562,8 +567,11 @@ const LabelStudioWrapper = ({ let temp = annotation.serializeAnnotation(); let ids = new Set(); let countLables = 0; + console.log(temp); temp.map((curr) => { - ids.add(curr.id); + if(curr.type !== "relation"){ + ids.add(curr.id); + } if(curr.type === "labels"){ countLables++; } @@ -581,10 +589,11 @@ const LabelStudioWrapper = ({ if (curr.from_name === "labels") acc.labels++; else if (["transcribed_json", "verbatim_transcribed_json"].includes(curr.from_name)) { - if (curr.value.text[0] === "") + if(curr.type === "relation"){ + if (curr.value.text[0] === "") acc.empty++; acc.textareas++; - } + }} return acc; }, { labels: 0, textareas: 0, empty: 0 } @@ -604,7 +613,9 @@ const LabelStudioWrapper = ({ let temp = annotation.serializeAnnotation(); for (let i = 0; i < temp.length; i++) { - if (temp[i].value.text) { + if(temp[i].type === "relation"){ + continue; + }else if (temp[i].value.text) { temp[i].value.text = [temp[i].value.text[0]]; } } @@ -994,7 +1005,9 @@ const LabelStudioWrapper = ({ let annotation = lsfRef.current.store.annotationStore.selected; let temp = annotation.serializeAnnotation(); for (let i = 0; i < temp.length; i++) { - if (temp[i].value.text) { + if(temp[i].type === "relation"){ + continue; + }else if (temp[i].value.text) { temp[i].value.text = [temp[i].value.text[0]]; } } diff --git a/src/ui/pages/container/Label-Studio/SuperCheckerLSF.jsx b/src/ui/pages/container/Label-Studio/SuperCheckerLSF.jsx index 689cb9647..74aea942b 100644 --- a/src/ui/pages/container/Label-Studio/SuperCheckerLSF.jsx +++ b/src/ui/pages/container/Label-Studio/SuperCheckerLSF.jsx @@ -35,7 +35,7 @@ import APITransport from "../../../../redux/actions/apitransport/apitransport"; import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; import getTaskAssignedUsers from '../../../../utils/getTaskAssignedUsers'; import LightTooltip from "../../component/common/Tooltip"; - +import keymap from "./keymap"; import { getProjectsandTasks, getNextProject, @@ -188,13 +188,16 @@ const LabelStudioWrapper = ({ } }, [userData]); */ - useEffect(() => { +useEffect(() => { let sidePanel = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + let showLabelsOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + let selectAfterCreateOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); + let continousLabelingOnly = ProjectDetails?.project_type?.includes("OCRSegmentCategorization"); localStorage.setItem( "labelStudio:settings", JSON.stringify({ bottomSidePanel: !sidePanel, - continuousLabeling: false, + continuousLabeling: continousLabelingOnly, enableAutoSave: false, enableHotkeys: true, enableLabelTooltips: true, @@ -202,9 +205,9 @@ const LabelStudioWrapper = ({ enableTooltips: false, fullscreen: false, imageFullSize: false, - selectAfterCreate: false, + selectAfterCreate: selectAfterCreateOnly, showAnnotationsPanel: true, - showLabels: false, + showLabels: showLabelsOnly, showLineNumbers: false, showPredictionsPanel: true, sidePanelMode: "SIDEPANEL_MODE_REGIONS", @@ -328,6 +331,7 @@ const LabelStudioWrapper = ({ id: taskData.id, data: taskData.data, }, + keymap: keymap, onLabelStudioLoad: function (ls) { // if (taskData.correct_annotation) { @@ -384,7 +388,9 @@ const LabelStudioWrapper = ({ let ids = new Set(); let countLables = 0; temp.map((curr) => { - ids.add(curr.id); + if(curr.type !== "relation"){ + ids.add(curr.id); + } if(curr.type === "labels"){ countLables++; } @@ -402,10 +408,12 @@ const LabelStudioWrapper = ({ if (curr.from_name === "labels") acc.labels++; else if (curr.from_name === "transcribed_json") { - if (curr.value.text[0] === "") + if(curr.type !== "relation"){ + if (curr.value.text[0] === "") acc.empty++; acc.textareas++; } + } return acc; }, { labels: 0, textareas: 0, empty: 0 } @@ -426,7 +434,9 @@ const LabelStudioWrapper = ({ ? [] : annotation.serializeAnnotation(); for (let i = 0; i < temp.length; i++) { - if (temp[i].value.text) { + if(temp[i].type === "relation"){ + continue; + }else if (temp[i].value.text) { temp[i].value.text = [temp[i].value.text[0]]; } } @@ -709,7 +719,9 @@ const LabelStudioWrapper = ({ let annotation = lsfRef.current.store.annotationStore.selected; let temp = annotation.serializeAnnotation(); for (let i = 0; i < temp.length; i++) { - if (temp[i].value.text) { + if(temp[i].type === "relation"){ + continue; + }else if (temp[i].value.text) { temp[i].value.text = [temp[i].value.text[0]]; } } diff --git a/src/ui/pages/container/Label-Studio/keymap.js b/src/ui/pages/container/Label-Studio/keymap.js new file mode 100644 index 000000000..fb7ca739d --- /dev/null +++ b/src/ui/pages/container/Label-Studio/keymap.js @@ -0,0 +1,8 @@ +const keymap ={ + "region:relation": { + "key": "alt+w", + "description": "Create relation between regions" + } +} + +export default keymap; \ No newline at end of file diff --git a/src/ui/pages/container/Label-Studio/labelConfigJSX.js b/src/ui/pages/container/Label-Studio/labelConfigJSX.js index 257dee755..f62594766 100644 --- a/src/ui/pages/container/Label-Studio/labelConfigJSX.js +++ b/src/ui/pages/container/Label-Studio/labelConfigJSX.js @@ -1,5 +1,8 @@ export const labelConfigJS = ` + - - -`; \ No newline at end of file + + + +`; diff --git a/src/ui/pages/container/Project/DeallocationAnnotatorsAndReviewers.jsx b/src/ui/pages/container/Project/DeallocationAnnotatorsAndReviewers.jsx index ea201323b..cf023d1c9 100644 --- a/src/ui/pages/container/Project/DeallocationAnnotatorsAndReviewers.jsx +++ b/src/ui/pages/container/Project/DeallocationAnnotatorsAndReviewers.jsx @@ -11,14 +11,15 @@ import FormControl from "@mui/material/FormControl"; import DatasetStyle from "../../../styles/Dataset"; import { translate } from "../../../../config/localisation"; import { useDispatch, useSelector } from "react-redux"; -import {useParams } from 'react-router-dom'; +import { useParams } from "react-router-dom"; import APITransport from '../../../../redux/actions/apitransport/apitransport'; import { snakeToTitleCase } from "../../../../utils/utils"; -import DeallocationAnnotatorsAndReviewersAPI from "../../../../redux/actions/api/ProjectDetails/DeallocationAnnotatorsAndReviewers"; +import DeallocationAnnotatorsAndReviewersAPI from "../../../../redux/actions/api/ProjectDetails/DeallocationAnnotatorsAndReviewers"; import CustomizedSnackbars from "../../component/common/Snackbar"; -import TextField from '@mui/material/TextField'; +import TextField from "@mui/material/TextField"; import LoginAPI from "../../../../redux/actions/api/UserManagement/Login"; - +import { DeallocateTaskById } from "../../../../redux/actions/api/ProjectDetails/DeallocationAnnotatorsAndReviewers"; +import { Tab, Tabs } from "@mui/material"; let AnnotationStatus = [ "unlabeled", @@ -28,18 +29,18 @@ let AnnotationStatus = [ "to_be_revised", ]; -let ReviewStatus = [ - "unreviewed", - "accepted", - "accepted_with_minor_changes", - "accepted_with_major_changes", - "to_be_revised", - "draft", - "skipped", - ]; +let ReviewStatus = [ + "unreviewed", + "accepted", + "accepted_with_minor_changes", + "accepted_with_major_changes", + "to_be_revised", + "draft", + "skipped", +]; - let SuperChecker = ["unvalidated","validated","validated_with_changes","skipped","draft","rejected"]; - const ITEM_HEIGHT = 48; +let SuperChecker = ["unvalidated","validated","validated_with_changes","skipped","draft","rejected"]; +const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; const MenuProps = { PaperProps: { @@ -61,122 +62,157 @@ const MenuProps = { }; export default function DeallocationAnnotatorsAndReviewers() { const classes = DatasetStyle(); - const dispatch = useDispatch(); - const {id} = useParams(); + const { id } = useParams(); const [anchorEl, setAnchorEl] = useState(null); - const [radiobutton, setRadiobutton] = useState("annotation"); + const [userLevel, setuserLevel] = useState("annotation"); const [openDialog, setOpenDialog] = useState(false); - const[annotatorsUser,setAnnotatorsUser] = useState("") - const[annotationStatus,setAnnotationStatus] = useState([]) - const[reviewerssUser,setReviewersUser] = useState("") - const[superCheckersUser,setSuperCheckersUser] = useState("") - const[reviewStatus,setReviewStatus] = useState([]) - const[superCheckStatus,setSuperCheckStatus] = useState([]) + const [annotatorsUser, setAnnotatorsUser] = useState(""); + const [annotationStatus, setAnnotationStatus] = useState([]); + const [reviewerssUser, setReviewersUser] = useState(""); + const [superCheckersUser, setSuperCheckersUser] = useState(""); + const [reviewStatus, setReviewStatus] = useState([]); + const [superCheckStatus, setSuperCheckStatus] = useState([]); + const [dealocateTasksBy, setDealocateTasksBy] = useState("taskId"); + const [dataIds, setdataIds] = useState(""); + const [snackbar, setSnackbarInfo] = useState({ open: false, message: "", variant: "success", -}); - - - + }); const open = Boolean(anchorEl); const Id = open ? "simple-popover" : undefined; - const ProjectDetails = useSelector(state => state.getProjectDetails.data); + const ProjectDetails = useSelector((state) => state.getProjectDetails.data); const handleClickOpen = (event) => { setAnchorEl(event.currentTarget); }; - const handleClose = () => { setAnchorEl(null); - setAnnotatorsUser("") - setAnnotationStatus([]) - setReviewersUser("") - setReviewStatus([]) - setSuperCheckersUser("") - setSuperCheckStatus([]) + setAnnotatorsUser(""); + setAnnotationStatus([]); + setReviewersUser(""); + setReviewStatus([]); + setSuperCheckersUser(""); + setSuperCheckStatus([]); + }; + const handleUserLevelChange = (userLevel) => { + setuserLevel(userLevel); }; const handleAnnotation = () => { - setRadiobutton("annotation"); + setuserLevel("annotation"); }; const handleReview = () => { - setRadiobutton("review"); + setuserLevel("review"); }; const handlesuperChecker = () => { - setRadiobutton("superChecker"); + setuserLevel("superChecker"); }; const handleSubmit = () => { setAnchorEl(null); setOpenDialog(true); -} + }; -const handleCloseDialog = () => { + const handleCloseDialog = () => { setOpenDialog(false); - setAnnotatorsUser("") - setAnnotationStatus([]) - setReviewersUser("") - setReviewStatus([]) - setSuperCheckersUser("") - setSuperCheckStatus([]) -}; + setAnnotatorsUser(""); + setAnnotationStatus([]); + setReviewersUser(""); + setReviewStatus([]); + setSuperCheckersUser(""); + setSuperCheckStatus([]); + setdataIds(""); + }; -const handleChangeAnnotationStatus = (event) => { + const handleChangeAnnotationStatus = (event) => { const value = event.target.value; setAnnotationStatus(value); }; - const handleChangeReviewStatus = (event) =>{ + const handleChangeReviewStatus = (event) => { const value = event.target.value; setReviewStatus(value); - } - const handleChangeSuperCheckerStatus = (event) =>{ + }; + const handleChangeSuperCheckerStatus = (event) => { const value = event.target.value; setSuperCheckStatus(value); - } - - + }; -const handleok = async() => { + const handleok = async () => { setAnchorEl(null); setOpenDialog(false); - setAnnotatorsUser("") - setAnnotationStatus([]) - setReviewersUser("") - setReviewStatus([]) - setSuperCheckersUser("") - setSuperCheckStatus([]) - const projectObj = new DeallocationAnnotatorsAndReviewersAPI(id,radiobutton,annotatorsUser,reviewerssUser,annotationStatus,reviewStatus,superCheckersUser,superCheckStatus); + setAnnotatorsUser(""); + setAnnotationStatus([]); + setReviewersUser(""); + setReviewStatus([]); + setSuperCheckersUser(""); + setSuperCheckStatus([]); + setdataIds(""); + + if(dealocateTasksBy === "taskId"){ + const projectObj = new DeallocateTaskById(id, dataIds, userLevel,reviewerssUser,reviewStatus); + const res = await fetch(projectObj.apiEndPoint(), { + method: "POST", + body: JSON.stringify(projectObj.getBody()), + headers: projectObj.getHeaders(), + }); + + const resp = await res.json(); + // setLoading(false); + if (res.ok) { + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "success", + }); + } else { + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "error", + }); + } + } else { + + const projectObj = new DeallocationAnnotatorsAndReviewersAPI( + id, + userLevel, + annotatorsUser, + reviewerssUser, + annotationStatus, + reviewStatus, + superCheckersUser, + superCheckStatus + ); // dispatch(APITransport(projectObj)); const res = await fetch(projectObj.apiEndPoint(), { - method: "GET", - body: JSON.stringify(projectObj.getBody()), - headers: projectObj.getHeaders().headers, + method: "POST", + body: JSON.stringify(projectObj.getBody()), + headers: projectObj.getHeaders().headers, }); const resp = await res.json(); // setLoading(false); if (res.ok) { - setSnackbarInfo({ - open: true, - message: resp?.message, - variant: "success", - }) - + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "success", + }); } else { - setSnackbarInfo({ - open: true, - message: resp?.message, - variant: "error", - }) + setSnackbarInfo({ + open: true, + message: resp?.message, + variant: "error", + }); } -} - + } + }; -const renderSnackBar = () => { + const renderSnackBar = () => { return ( { /> ); }; + + + const [tabValue, setTabValue] = useState(0); + const handleTabChange = (e, v) => { + if(v === 0){ + setDealocateTasksBy("taskId"); + } else { + setDealocateTasksBy("userId"); + } + setTabValue(v); + + } const emailId = localStorage.getItem("email_id"); const [password, setPassword] = useState(""); const [pin, setPin] = useState(""); const handleConfirm = async () => { - if(radiobutton === "annotation" || radiobutton === "review"){ + if (userLevel === "annotation" || userLevel === "review") { const apiObj = new LoginAPI(emailId, password); const res = await fetch(apiObj.apiEndPoint(), { method: "POST", @@ -204,14 +252,14 @@ const renderSnackBar = () => { const rsp_data = await res.json(); if (res.ok) { handleok(); - }else{ + } else { window.alert("Invalid credentials, please try again"); console.log(rsp_data); } - }else if(radiobutton === "superChecker"){ - if(pin === "9327"){ + } else if (userLevel === "superChecker") { + if (pin === "9327") { handleok(); - }else{ + } else { window.alert("Incorrect pin entered"); } } @@ -219,7 +267,7 @@ const renderSnackBar = () => { return (
- {renderSnackBar()} + {renderSnackBar()} { - - } - label="Annotators" - onClick={handleAnnotation} - /> - } - label="Reviewers" - onClick={handleReview} - /> - } - label="Super Check" - onClick={handlesuperChecker} - /> - + + + + + + + + + + {["annotation", "review", "superChecker"].map((userLevel) => ( + } + label={userLevel} + onClick={() => handleUserLevelChange(userLevel)} + /> + ))} + + + + - {radiobutton === "annotation" && ( + + {dealocateTasksBy === "taskId" && ( + + + + Project Task IDs: + + + + setdataIds(e.target.value)} + inputProps={{ + style: { + fontSize: "16px", + }, + }} + /> + + + )} + {userLevel === "annotation" && dealocateTasksBy === "userId" && ( <> - { )} - {radiobutton === "review" && ( + {userLevel === "review" && dealocateTasksBy === "userId" && ( <> - { )} - - {radiobutton === "superChecker" && ( + {userLevel === "superChecker" && dealocateTasksBy === "userId" && ( <> - { )} -
); -} +} \ No newline at end of file diff --git a/src/ui/pages/container/Transliteration/Transliteration.jsx b/src/ui/pages/container/Transliteration/Transliteration.jsx index 1c4df60cd..799e9f6c3 100644 --- a/src/ui/pages/container/Transliteration/Transliteration.jsx +++ b/src/ui/pages/container/Transliteration/Transliteration.jsx @@ -1,8 +1,8 @@ -import React, { useEffect, useState ,useRef} from "react"; +import React, { useEffect, useState ,useRef, useDebugValue} from "react"; import { TextField } from "@mui/material"; import { Autocomplete, Box, Button, Card, Grid, Typography } from "@mui/material"; import { IndicTransliterate, getTransliterationLanguages, getTransliterateSuggestions } from "@ai4bharat/indic-transliterate"; -import "@ai4bharat/indic-transliterate/dist/index.css"; +import "../../../../IndicTransliterate/index.css"; import GlobalStyles from "../../../styles/LayoutStyles"; import CustomizedSnackbars from "../../component/common/Snackbar"; import TransliterationAPI from "../../../../redux/actions/api/Transliteration/TransliterationAPI"; @@ -21,8 +21,8 @@ const Transliteration = (props) => { const suggestionRef = useRef([null]); const newKeystrokesRef = useRef(); const [flag, setflag] = useState(); - const [debouncedText, setDebouncedText] = useState(""); - const debouncedTextRef = useRef(""); + // const [debouncedText, setDebouncedText] = useState(""); + // const debouncedTextRef = useRef(""); const [showSnackBar, setShowSnackBar] = useState({ message: "", variant: "", @@ -36,7 +36,7 @@ const Transliteration = (props) => { let searchFilters = JSON.parse(localStorage.getItem("TaskData")); var data = languageList.filter((e) => e.DisplayName.includes(ProjectDetails.tgt_language)); -console.log("nnn",data,ProjectDetails,searchFilters); +// console.log("nnn",data,ProjectDetails,searchFilters); useEffect(() => { if (params.taskId) { setText(searchFilters?.data?.machine_translation); @@ -46,73 +46,70 @@ console.log("nnn",data,ProjectDetails,searchFilters); }, []); -console.log(isSpaceClicked); +// console.log(isSpaceClicked); + // useEffect(() => { + // console.log(logJsonArray); + // }, [logJsonArray]) - useEffect(() => { - console.log("nnn","useEffect is running",prev); - const processConsoleLog = (args) => { - const msg = JSON.stringify(args); - if (msg.includes('library data')) { - const dataMatch = JSON.parse(msg.match(/{[^}]*}/)); - setflag(dataMatch.result) - return dataMatch.result; - } - return ; - }; - const originalConsoleLog = console.log; - console.log = (...args) => { - const newSuggestions = processConsoleLog(args); - if (newSuggestions!=null) { - suggestionRef.current = prev==true?flag:newSuggestions - } - originalConsoleLog(...args); - }; + // useEffect(() => { + // console.log("nnn","useEffect is running",prev); + // const processConsoleLog = (args) => { + // const msg = JSON.stringify(args); + // if (msg.includes('library data')) { + // const dataMatch = JSON.parse(msg.match(/{[^}]*}/)); + // setflag(dataMatch.result) + // return dataMatch.result; + // } + // return ; + // }; + // const originalConsoleLog = console.log; + // console.log = (...args) => { + // const newSuggestions = processConsoleLog(args); + // if (newSuggestions!=null) { + // suggestionRef.current = prev==true?flag:newSuggestions + // } + // originalConsoleLog(...args); + // }; - return () => { - console.log = originalConsoleLog; - }; - }, [debouncedTextRef.current,prev,selectedLang.LangCode]); + // return () => { + // console.log = originalConsoleLog; + // }; + // }, [debouncedTextRef.current,prev,selectedLang.LangCode]); - useEffect(() => { - if (debouncedTextRef.current.trim()!="" && suggestionRef.current.length>1) { - console.log("nnn",suggestionRef.current); - console.log("nnn",debouncedTextRef.current,text); - const words = debouncedTextRef.current.split(/\s+/).filter(word => word.trim() !== ""); - - const optedWord = suggestionRef.current.find((item) => item === words[words.length-1]) || ""; + // useEffect(() => { + // if (debouncedTextRef.current.trim()!="" && suggestionRef.current.length>1) { + // console.log("nnn",suggestionRef.current); + // console.log("nnn",debouncedTextRef.current,text); + // const words = debouncedTextRef.current.split(/\s+/).filter(word => word.trim() !== ""); - const newKeystroke = { - keystrokes: debouncedTextRef.current, - results: suggestionRef.current, - opted:optedWord, - created_at: new Date().toISOString(), - }; - newKeystrokesRef.current = newKeystroke - if ( - keystrokesRef.current.length > 0 && - keystrokesRef.current[keystrokesRef.current.length - 1].keystrokes === newKeystroke.keystrokes - ) { - keystrokesRef.current[keystrokesRef.current.length - 1] = newKeystroke; - } else { - keystrokesRef.current = [...keystrokesRef.current, newKeystroke]; - } - console.log("nnn", keystrokesRef.current,newKeystrokesRef.current); - const finalJson = { - word: debouncedTextRef.current, - steps: keystrokesRef.current, - language: selectedLang.LangCode!=undefined?selectedLang.LangCode:"hi", - }; - localStorage.setItem('TransliterateLogging', JSON.stringify(finalJson)); - } - }, [suggestionRef.current,prev,selectedLang.LangCode]); + // const optedWord = suggestionRef.current.find((item) => item === words[words.length-1]) || ""; -useEffect(()=>{ - if (isSpaceClicked==true) { - json() - } -},[isSpaceClicked]) + // const newKeystroke = { + // keystrokes: debouncedTextRef.current, + // results: suggestionRef.current, + // opted:optedWord, + // created_at: new Date().toISOString(), + // }; + // newKeystrokesRef.current = newKeystroke + // if ( + // keystrokesRef.current.length > 0 && + // keystrokesRef.current[keystrokesRef.current.length - 1].keystrokes === newKeystroke.keystrokes + // ) { + // keystrokesRef.current[keystrokesRef.current.length - 1] = newKeystroke; + // } else { + // keystrokesRef.current = [...keystrokesRef.current, newKeystroke]; + // } + // console.log("nnn", keystrokesRef.current,newKeystrokesRef.current); + // const finalJson = { + // word: debouncedTextRef.current, + // steps: keystrokesRef.current, + // language: selectedLang.LangCode!=undefined?selectedLang.LangCode:"hi", + // }; + // localStorage.setItem('TransliterateLogging', JSON.stringify(finalJson)); + // } + // }, [suggestionRef.current,prev,selectedLang.LangCode]); const renderTextarea = (props) => { return ( @@ -124,29 +121,33 @@ useEffect(()=>{ /> ); }; -const json=()=>{ - const api = localStorage.getItem('TransliterateLogging'); - const transliterateObj = new TransliterationAPI(JSON.parse(api)); - fetch(transliterateObj.apiEndPoint(), { - method: "POST", - body: JSON.stringify(transliterateObj.getBody()), - headers: transliterateObj.getHeaders().headers, - }) - .then(async (res) => { - if (!res.ok) throw await res.json(); - else return await res.json(); - }) - .then((res) => { - setShowSnackBar({ open: true, message: res.message, variant: "success" }); - console.log("success"); - }) - .catch((err) => { - setShowSnackBar({ open: true, message: err.message, variant: "error" }); - console.log("error", err); - }); - setIsSpaceClicked(false) -} +// const json=()=>{ +// let tempLogJsonArray = logJsonArray; +// tempLogJsonArray.shift(); +// tempLogJsonArray.shift(); +// const finalJson = {"word": text, "source": "shoonya-frontend", "language": selectedLang.LangCode!=undefined?selectedLang.LangCode:"hi", "steps":tempLogJsonArray}; +// const transliterateObj = new TransliterationAPI(finalJson); +// fetch(transliterateObj.apiEndPoint(), { +// method: "POST", +// body: JSON.stringify(transliterateObj.getBody()), +// headers: transliterateObj.getHeaders().headers, +// }) +// .then(async (res) => { +// if (!res.ok) throw await res.json(); +// else return await res.json(); +// }) +// .then((res) => { +// setShowSnackBar({ open: true, message: res.message, variant: "success" }); +// console.log("success"); +// }) +// .catch((err) => { +// setShowSnackBar({ open: true, message: err.message, variant: "error" }); +// console.log("error", err); +// }); +// setLogJsonArray([]); +// setIsSpaceClicked(false) +// } useEffect(() => { getTransliterationLanguages() @@ -160,7 +161,7 @@ const json=()=>{ const handleLanguageChange = (event, val) => { setSelectedLang(val); - setIsSpaceClicked(true) + // setIsSpaceClicked(true) }; @@ -175,8 +176,8 @@ const json=()=>{ }); }; const onCloseButtonClick = async () => { - console.log("kkkk"); - json() + // console.log("kkkk"); + // json() setShowTransliterationModel(false); }; const handleSnackBarClose = () => { @@ -229,18 +230,17 @@ const json=()=>{ value={text} onChangeText={(val) => { setText(val) - setDebouncedText(val); - debouncedTextRef.current=val - if(!debouncedTextRef.current.toString().includes(debouncedText)){ - setprev(true) - } - else{ - setprev(false) - } - console.log("nnn",text,debouncedText,debouncedTextRef.current); + // setDebouncedText(val); + // debouncedTextRef.current=val + // if(!debouncedTextRef.current.toString().includes(debouncedText)){ + // setprev(true) + // } + // else{ + // setprev(false) + // } + // console.log("nnn",text,debouncedText,debouncedTextRef.current); }} renderComponent={(props) => renderTextarea(props)} - showCurrentWordAsLastSuggestion={true} /> { localStorage.setItem("shoonya_access_token", rsp_data.access); localStorage.setItem("shoonya_refresh_token", rsp_data.refresh); localStorage.setItem("email_id", credentials.email.toLowerCase()); + localStorage.setItem("userCustomTranscriptionSettings", JSON.stringify({})) getLoggedInUserData(); // setLoading(false); } else{