diff --git a/check-circular-deps.js b/check-circular-deps.js new file mode 100644 index 0000000000..f340787974 --- /dev/null +++ b/check-circular-deps.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node +const {execSync} = require('child_process') + +let cycles +try { + const output = execSync( + 'npx madge --circular --extensions js --json public/js/', + {encoding: 'utf8', maxBuffer: 10 * 1024 * 1024}, + ) + cycles = JSON.parse(output) +} catch (e) { + if (e.stdout) { + cycles = JSON.parse(e.stdout) + } else { + console.error('Failed to run madge:', e.message) + process.exit(1) + } +} + +if (cycles.length > 0) { + console.error( + `\x1b[31m✖ Found ${cycles.length} circular dependencies:\x1b[0m\n`, + ) + cycles.forEach((cycle, i) => { + console.error(` ${i + 1}) ${cycle.join(' → ')}`) + }) + process.exit(1) +} else { + console.log('\x1b[32m✔ No circular dependencies\x1b[0m') +} diff --git a/package.json b/package.json index b179c941d2..90458f9da0 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "watch": "sed -i \"s/version .*/version = \\\"v${npm_package_version}\\\"/g\" ./nodejs/config.ini && webpack --mode development --watch", "build:dev": "sed -i \"s/version .*/version = \\\"v${npm_package_version}\\\"/g\" ./nodejs/config.ini && webpack --mode development", "build:production": "webpack --mode production", + "check:circular-deps": "node check-circular-deps.js", "prepare": "husky" }, "workspaces": [ @@ -87,6 +88,7 @@ "jest-environment-jsdom": "^30.0.0", "jest-transform-css": "^6.0.1", "lint-staged": ">=10", + "madge": "^8.0.0", "mini-css-extract-plugin": "^2.7.6", "msw": "^2.7.3", "prettier": "^3.0.0", diff --git a/plugins/airbnb b/plugins/airbnb index ac7921b89a..0d6152c9c4 160000 --- a/plugins/airbnb +++ b/plugins/airbnb @@ -1 +1 @@ -Subproject commit ac7921b89aae4e3f0b9ab03851c993d99f2db755 +Subproject commit 0d6152c9c48bff972f5b7a591b507389d0a830e0 diff --git a/plugins/translated b/plugins/translated index b3f19a2db6..c957a29a76 160000 --- a/plugins/translated +++ b/plugins/translated @@ -1 +1 @@ -Subproject commit b3f19a2db6f36dc8a2fa278eb0df5c2135404fa5 +Subproject commit c957a29a768561735bdec0276d7fce45aeedcecd diff --git a/plugins/uber b/plugins/uber index c6beac3fda..cc5299817e 160000 --- a/plugins/uber +++ b/plugins/uber @@ -1 +1 @@ -Subproject commit c6beac3fdacce11cc78db017ddf41fdb7fd766c7 +Subproject commit cc5299817e346708c072bb2643362d0b69f466b6 diff --git a/public/img/icons/ChangePassword.js b/public/img/icons/ChangePassword.js index e257ab75ce..3b67662d4d 100644 --- a/public/img/icons/ChangePassword.js +++ b/public/img/icons/ChangePassword.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' const ChangePassword = ({size = 24}) => { return ( - + diff --git a/public/js/actions/CatToolActions.js b/public/js/actions/CatToolActions.js index 23c7b4680b..95d5dbedc7 100644 --- a/public/js/actions/CatToolActions.js +++ b/public/js/actions/CatToolActions.js @@ -1,5 +1,5 @@ import AppDispatcher from '../stores/AppDispatcher' -import RevisionFeedbackModal from '../components/modals/RevisionFeedbackModal' +import {MODAL_KEY} from '../constants/ModalKeys' import CommonUtils from '../utils/commonUtils' import CatToolStore from '../stores/CatToolStore' import {getJobStatistics} from '../api/getJobStatistics' @@ -11,12 +11,15 @@ import {checkJobKeysHaveGlossary} from '../api/checkJobKeysHaveGlossary' import {getJobMetadata} from '../api/getJobMetadata' import CatToolConstants from '../constants/CatToolConstants' import SegmentStore from '../stores/SegmentStore' -import ConfirmMessageModal from '../components/modals/ConfirmMessageModal' +import {updateGlobalWarnings} from './warningActions' import {getGlobalWarnings} from '../api/getGlobalWarnings' -import SegmentActions from './SegmentActions' -import OfflineUtils from '../utils/offlineUtils' -import AlertModal from '../components/modals/AlertModal' import {isUndefined} from 'lodash' +import { + addNotification, + removeNotification, + removeAllNotifications, +} from './notificationActions' +import OfflineUtils from '../utils/offlineUtils' let CatToolActions = { popupInfoUserMenu: () => 'infoUserMenu-' + config.userMail, @@ -121,7 +124,7 @@ let CatToolActions = { }, } ModalsActions.showModalComponent( - RevisionFeedbackModal, + MODAL_KEY.REVISION_FEEDBACK, props, 'Feedback submission', ) @@ -210,24 +213,9 @@ let CatToolActions = { * autoDismiss: (Boolean, Default true) Set if notification is dismissible by the user. * */ - addNotification: function (notification) { - return AppDispatcher.dispatch({ - actionType: CatToolConstants.ADD_NOTIFICATION, - notification, - }) - }, - removeNotification: function (notification) { - AppDispatcher.dispatch({ - actionType: CatToolConstants.REMOVE_NOTIFICATION, - notification, - }) - }, - - removeAllNotifications: function () { - AppDispatcher.dispatch({ - actionType: CatToolConstants.REMOVE_ALL_NOTIFICATION, - }) - }, + addNotification, + removeNotification, + removeAllNotifications, onRender: (props = {}) => { SegmentStore.nextUntranslatedFromServer = null @@ -313,7 +301,7 @@ let CatToolActions = { }, } ModalsActions.showModalComponent( - ConfirmMessageModal, + MODAL_KEY.CONFIRM_MESSAGE, props, 'Lara Free Plan Limit Reached', ) @@ -356,7 +344,7 @@ let CatToolActions = { //check for errors if (data.details) { - SegmentActions.updateGlobalWarnings(data.details) + updateGlobalWarnings(data.details) } CommonUtils.dispatchCustomEvent('getWarning:global:success') }) @@ -372,7 +360,7 @@ let CatToolActions = { if (operation === 'setTranslation') { if (codeInt === -5) { ModalsActions.showModalComponent( - AlertModal, + MODAL_KEY.ALERT, { text: 'This segment has been disabled by the project owner.
Refresh the page to update segment status.', buttonText: 'Refresh page', @@ -382,7 +370,7 @@ let CatToolActions = { ) } else if (codeInt !== -10) { ModalsActions.showModalComponent( - AlertModal, + MODAL_KEY.ALERT, { text: 'Error in saving the translation. Try the following:
1) Refresh the page (Ctrl+F5 twice)
2) Clear the cache in the browser
If the solutions above does not resolve the issue, please stop the translation and report the problem to support@matecat.com', }, @@ -393,7 +381,7 @@ let CatToolActions = { if (codeInt === -10 && operation !== 'getSegments') { ModalsActions.showModalComponent( - AlertModal, + MODAL_KEY.ALERT, { text: 'Job canceled or assigned to another translator', successCallback: () => location.reload, @@ -408,7 +396,7 @@ let CatToolActions = { if (codeInt === -2000 && !isUndefined(error.message)) { ModalsActions.showModalComponent( - AlertModal, + MODAL_KEY.ALERT, { /* text: 'You cannot change the status of an ICE segment to "Translated" without editing it first.
' + diff --git a/public/js/actions/CatToolActions.test.js b/public/js/actions/CatToolActions.test.js index 3c764ad230..de6ccc7447 100644 --- a/public/js/actions/CatToolActions.test.js +++ b/public/js/actions/CatToolActions.test.js @@ -43,6 +43,10 @@ jest.mock('../components/modals/AlertModal', () => 'AlertModal') jest.mock('../components/modals/RevisionFeedbackModal', () => 'RevisionFeedbackModal') jest.mock('../components/modals/ConfirmMessageModal', () => 'ConfirmMessageModal') +jest.mock('../constants/ModalKeys', () => ({ + MODAL_KEY: {ALERT: 'Alert', COPY_SOURCE: 'CopySource'}, + COPY_SOURCE_COOKIE: 'copySourceCookie', +})) jest.mock('../constants/CatToolConstants', () => ({ SET_FIRST_LOAD: 'SET_FIRST_LOAD', })) @@ -52,7 +56,6 @@ jest.mock('lodash', () => ({ import CatToolActions from './CatToolActions' import ModalsActions from './ModalsActions' -import AlertModal from '../components/modals/AlertModal' describe('CatToolActions.processErrors', () => { beforeEach(() => { @@ -68,7 +71,7 @@ describe('CatToolActions.processErrors', () => { CatToolActions.processErrors([{code: '-5'}], 'setTranslation') expect(ModalsActions.showModalComponent).toHaveBeenCalledWith( - AlertModal, + 'Alert', expect.objectContaining({ text: 'This segment has been disabled by the project owner.
Refresh the page to update segment status.', buttonText: 'Refresh page', @@ -86,7 +89,7 @@ describe('CatToolActions.processErrors', () => { CatToolActions.processErrors([{code: '-1'}], 'setTranslation') expect(ModalsActions.showModalComponent).toHaveBeenCalledWith( - AlertModal, + 'Alert', expect.objectContaining({ text: expect.stringContaining('Error in saving the translation'), }), @@ -111,7 +114,7 @@ describe('CatToolActions.processErrors', () => { CatToolActions.processErrors([{code: '-10'}], 'setSuggestion') expect(ModalsActions.showModalComponent).toHaveBeenCalledWith( - AlertModal, + 'Alert', expect.objectContaining({ text: 'Job canceled or assigned to another translator', successCallback: expect.any(Function), diff --git a/public/js/actions/ModalsActions.js b/public/js/actions/ModalsActions.js index 21299d59f8..a3ed4eea34 100644 --- a/public/js/actions/ModalsActions.js +++ b/public/js/actions/ModalsActions.js @@ -1,14 +1,8 @@ -import ConfirmMessageModal from '../components/modals/ConfirmMessageModal' -import SplitJobModal from '../components/modals/SplitJob' -import {CreateTeam} from '../components/modals/CreateTeam' -import {ModifyTeam} from '../components/modals/ModifyTeam' import {mergeJobChunks} from '../api/mergeJobChunks' import AppDispatcher from '../stores/AppDispatcher' import ModalsConstants from '../constants/ModalsConstants' -import PreferencesModal from '../components/modals/PreferencesModal' -import SuccessModal from '../components/modals/SuccessModal' -import OnBoarding, {ONBOARDING_STEP} from '../components/onBoarding/OnBoarding' -import {DownloadAlertModal} from '../components/modals/DownloadAlertModal' +import {MODAL_KEY} from '../constants/ModalKeys' +import {ONBOARDING_STEP} from '../constants/OnBoardingConstants' let ModalsActions = { showModalComponent: ( @@ -35,7 +29,7 @@ let ModalsActions = { }, openLoginModal: function () { ModalsActions.showModalComponent( - OnBoarding, + MODAL_KEY.ONBOARDING, {isCloseButtonEnabled: true}, null, {maxWidth: 'unset', width: 'auto'}, @@ -46,7 +40,7 @@ let ModalsActions = { }, openRegisterModal: () => { ModalsActions.showModalComponent( - OnBoarding, + MODAL_KEY.ONBOARDING, { step: ONBOARDING_STEP.REGISTER, isCloseButtonEnabled: true, @@ -64,18 +58,18 @@ let ModalsActions = { maxWidth: '700px', } ModalsActions.showModalComponent( - PreferencesModal, + MODAL_KEY.PREFERENCES, {showGDriveMessage}, 'Profile', style, ) }, openSuccessModal: (props) => { - ModalsActions.showModalComponent(SuccessModal, props, props.title) + ModalsActions.showModalComponent(MODAL_KEY.SUCCESS, props, props.title) }, openResetPassword: ({setNewPassword = false} = {}) => { ModalsActions.showModalComponent( - OnBoarding, + MODAL_KEY.ONBOARDING, { step: setNewPassword ? ONBOARDING_STEP.SET_NEW_PASSWORD @@ -95,14 +89,14 @@ let ModalsActions = { }) }, openCreateTeamModal: function () { - this.showModalComponent(CreateTeam, {}, 'Create New Team') + this.showModalComponent(MODAL_KEY.CREATE_TEAM, {}, 'Create New Team') }, openModifyTeamModal: function (team, hideChangeName) { const props = { team: team, hideChangeName: hideChangeName, } - this.showModalComponent(ModifyTeam, props, 'Manage Team') + this.showModalComponent(MODAL_KEY.MODIFY_TEAM, props, 'Manage Team') }, openSplitJobModal: function (job, project, callback) { @@ -112,7 +106,7 @@ let ModalsActions = { callback: callback, } const style = {width: '670px', maxWidth: '670px'} - this.showModalComponent(SplitJobModal, props, 'Split Job', style) + this.showModalComponent(MODAL_KEY.SPLIT_JOB, props, 'Split Job', style) }, openMergeModal: function (project, job, successCallback) { const props = { @@ -133,7 +127,11 @@ let ModalsActions = { this.onCloseModal() }, } - this.showModalComponent(ConfirmMessageModal, props, 'Confirmation required') + this.showModalComponent( + MODAL_KEY.CONFIRM_MESSAGE, + props, + 'Confirmation required', + ) }, showDownloadWarningsModal: function ( @@ -142,7 +140,7 @@ let ModalsActions = { cancelCallback, ) { ModalsActions.showModalComponent( - DownloadAlertModal, + MODAL_KEY.DOWNLOAD_ALERT, {successCallback, successCallbackWithoutErrors, cancelCallback}, 'Unresolved Major Issues', ) diff --git a/public/js/actions/SegmentActions.js b/public/js/actions/SegmentActions.js index 931c9fd441..fdb48821b9 100644 --- a/public/js/actions/SegmentActions.js +++ b/public/js/actions/SegmentActions.js @@ -6,16 +6,9 @@ import $ from 'jquery' import AppDispatcher from '../stores/AppDispatcher' import SegmentConstants from '../constants/SegmentConstants' import EditAreaConstants from '../constants/EditAreaConstants' -import CatToolConstants from '../constants/CatToolConstants' import SegmentStore from '../stores/SegmentStore' -import TranslationMatches from '../components/segments/utils/translationMatches' -import OfflineUtils from '../utils/offlineUtils' -import SegmentUtils from '../utils/segmentUtils' -import CopySourceModal, { - COPY_SOURCE_COOKIE, -} from '../components/modals/CopySourceModal' -import CatToolActions from './CatToolActions' -import ConfirmMessageModal from '../components/modals/ConfirmMessageModal' +import {MODAL_KEY, COPY_SOURCE_COOKIE} from '../constants/ModalKeys' +import ModalsActions from './ModalsActions' import {getGlossaryForSegment} from '../api/getGlossaryForSegment' import {getGlossaryMatch} from '../api/getGlossaryMatch' import {deleteGlossaryItem} from '../api/deleteGlossaryItem' @@ -25,32 +18,63 @@ import {approveSegments} from '../api/approveSegments' import {translateSegments} from '../api/translateSegments' import {splitSegment} from '../api/splitSegment' import {copyAllSourceToTarget} from '../api/copyAllSourceToTarget' -import AlertModal from '../components/modals/AlertModal' -import ModalsActions from './ModalsActions' -import {getLocalWarnings} from '../api/getLocalWarnings' -import {getGlossaryCheck} from '../api/getGlossaryCheck' import CatToolStore from '../stores/CatToolStore' -import DraftMatecatUtils from '../components/segments/utils/DraftMatecatUtils' import {deleteSegmentIssue as deleteSegmentIssueApi} from '../api/deleteSegmentIssue' -import SegmentsFilterUtil from '../components/header/cattol/segment_filter/segment_filter' import {REVISE_STEP_NUMBER, SEGMENTS_STATUS} from '../constants/Constants' import {getSegmentsIssues} from '../api/getSegmentsIssues' import {getSegmentVersionsIssues} from '../api/getSegmentVersionsIssues' import {sendSegmentVersionIssueComment} from '../api/sendSegmentVersionIssueComment' -import { - HIDE_UNLOCK_ALL_SEGMENTS_MODAL_STORAGE, - UnlockAllSegmentsModal, -} from '../components/modals/UnlockAllSegmentsModal' import {getTagProjection} from '../api/getTagProjection' import {setCurrentSegment} from '../api/setCurrentSegment' -import CommonUtils from '../utils/commonUtils' +import {setLastSegmentFromLocalStorage} from '../utils/segmentLocalStorage' +import {addNotification} from './notificationActions' +import {updateGlobalWarnings} from './warningActions' +import {addClassToSegment, removeClassToSegment} from './segmentClassActions' +import {getSegmentsQa, startSegmentQACheck} from './segmentQaActions' +import {disableTPOnSegment} from './tagProjectionActions' +import TranslationMatches from '../components/segments/utils/translationMatches' +import { + setStatus, + setHeaderPercentage, + hideSegmentHeader, + setSegmentPropagation, + modifiedTranslation, + replaceEditAreaTextContent, + setChoosenSuggestion, + setSegmentContributions, + setSegmentSaving, + setMutedSegments, + removeAllMutedSegments, + activateTab, + highlightGlossaryTerm, + addSearchResultToSegments, + removeSearchResultToSegments, + qaComponentsetLxqIssues, + addLexiqaHighlight, + setSegmentWarnings, + setSegmentAsTagged, +} from './segmentDispatchActions' +import CatToolActions from './CatToolActions' +import OfflineUtils from '../utils/offlineUtils' +import DraftMatecatUtils from '../components/segments/utils/DraftMatecatUtils' +import SegmentUtils from '../utils/segmentUtils' import {getTranslationMismatches as getTranslationMismatchesApi} from '../api/getTranslationMismatches' import TextUtils from '../utils/textUtils' -import { - segmentTranslation, - translationIsToSaveBeforeClose, -} from '../setTranslationUtil' -import {TAB} from '../components/segments/SegmentFooter' +import {TAB} from '../constants/SegmentTabConstants' + +// Lazy-loaded to break circular dependencies +// Using require() instead of import so madge's ES6 detective doesn't +// register these as static edges — webpack still resolves them correctly +// at call time. +let _SegmentsFilterUtil +let _SetTranslationUtil +const getSegmentsFilterUtil = () => + _SegmentsFilterUtil || + (_SegmentsFilterUtil = + require('../components/header/cattol/segment_filter/segment_filter').default) +const getSetTranslationUtil = () => + _SetTranslationUtil || + (_SetTranslationUtil = require('../setTranslationUtil')) const SegmentActions = { localStorageCommentsClosed: @@ -90,7 +114,7 @@ const SegmentActions = { : 'We got an error, please contact support', type: 'error', } - CatToolActions.addNotification(notification) + addNotification(notification) SegmentActions.freezingSegments(false) }) }, @@ -108,31 +132,14 @@ const SegmentActions = { }) }, - addSearchResultToSegments: function ( - occurrencesList, - searchResultsDictionary, - currentIndex, - text, - ) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.ADD_SEARCH_RESULTS, - occurrencesList, - searchResultsDictionary, - currentIndex, - text, - }) - }, + addSearchResultToSegments, changeCurrentSearchSegment: function (currentIndex) { AppDispatcher.dispatch({ actionType: SegmentConstants.ADD_CURRENT_SEARCH, currentIndex, }) }, - removeSearchResultToSegments: function () { - AppDispatcher.dispatch({ - actionType: SegmentConstants.REMOVE_SEARCH_RESULTS, - }) - }, + removeSearchResultToSegments, replaceCurrentSearch: function (text) { AppDispatcher.dispatch({ actionType: EditAreaConstants.REPLACE_SEARCH_RESULTS, @@ -180,8 +187,13 @@ const SegmentActions = { this.closeIssuesPanel() }, saveSegmentBeforeClose: function (segment) { - if (translationIsToSaveBeforeClose(segment)) { - return segmentTranslation(segment, SEGMENTS_STATUS.DRAFT, () => {}, false) + if (getSetTranslationUtil().translationIsToSaveBeforeClose(segment)) { + return getSetTranslationUtil().segmentTranslation( + segment, + SEGMENTS_STATUS.DRAFT, + () => {}, + false, + ) } else { return Promise.resolve() } @@ -210,38 +222,11 @@ const SegmentActions = { }) } }, - addClassToSegment: function (sid, newClass) { - setTimeout(function () { - AppDispatcher.dispatch({ - actionType: SegmentConstants.ADD_SEGMENT_CLASS, - id: sid, - newClass: newClass, - }) - }, 0) - }, + addClassToSegment, - removeClassToSegment: function (sid, className) { - if (sid) { - setTimeout(function () { - AppDispatcher.dispatch({ - actionType: SegmentConstants.REMOVE_SEGMENT_CLASS, - id: sid, - className: className, - }) - }, 0) - } - }, + removeClassToSegment, - setStatus: function (sid, fid, status) { - if (sid) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.SET_SEGMENT_STATUS, - id: sid, - fid: fid, - status: status, - }) - } - }, + setStatus, clickOnApprovedButton: function (segment, goToNextUnapproved) { // the event click: 'A.APPROVED' i need to specify the tag a and not only the class @@ -300,7 +285,7 @@ const SegmentActions = { config.revisionNumber === REVISE_STEP_NUMBER.REVISE1 ? SEGMENTS_STATUS.APPROVED : SEGMENTS_STATUS.APPROVED2 - segmentTranslation(segment, status, afterApproveFn) + getSetTranslationUtil().segmentTranslation(segment, status, afterApproveFn) // Lock the segment if it's approved in a second pass but was previously approved in first revision if (config.revisionNumber > 1) { SegmentUtils.removeUnlockedSegment(sid) @@ -352,27 +337,16 @@ const SegmentActions = { } } - segmentTranslation(segment, SEGMENTS_STATUS.TRANSLATED, afterTranslateFn) + getSetTranslationUtil().segmentTranslation( + segment, + SEGMENTS_STATUS.TRANSLATED, + afterTranslateFn, + ) }, - setHeaderPercentage: function (sid, fid, match, className, createdBy) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.SET_SEGMENT_HEADER, - id: sid, - fid: fid, - match, - className: className, - createdBy: createdBy, - }) - }, + setHeaderPercentage, - hideSegmentHeader: function (sid, fid) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.HIDE_SEGMENT_HEADER, - id: sid, - fid: fid, - }) - }, + hideSegmentHeader, propagateTranslation: function (segmentId, propagatedSegments, status) { const segment = SegmentStore.getSegmentByIdToJS(segmentId) @@ -403,15 +377,7 @@ const SegmentActions = { SegmentActions.setAlternatives(segmentId, undefined) }, - setSegmentPropagation: function (sid, fid, propagation, from) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.SET_SEGMENT_PROPAGATION, - id: sid, - fid: fid, - propagation: propagation, - from: from, - }) - }, + setSegmentPropagation, /*++++++++++ Tag Proj start ++++++++++*/ startSegmentTagProjection: function (sid) { SegmentActions.getSegmentTagsProjection(sid) @@ -446,12 +412,7 @@ const SegmentActions = { SegmentActions.startSegmentQACheck() }) }, - startSegmentQACheck: function () { - clearTimeout(SegmentActions.pendingQACheck) - SegmentActions.pendingQACheck = setTimeout(function () { - SegmentActions.getSegmentsQa(SegmentStore.getCurrentSegment()) - }, config.segmentQACheckInterval) - }, + startSegmentQACheck, /** * Tag Projection: get the tag projection for the current segment * @returns translation with the Tag projection @@ -493,60 +454,15 @@ const SegmentActions = { /** * Disable the Tag Projection, for example after clicking on the Translation Matches */ - disableTPOnSegment: function (segmentObj) { - var currentSegment = segmentObj - ? segmentObj - : SegmentStore.getCurrentSegment() - - if (!currentSegment) return - - var tagProjectionEnabled = - DraftMatecatUtils.hasDataOriginalTags(currentSegment.segment) && - !currentSegment.tagged - if (SegmentUtils.checkTPEnabled() && tagProjectionEnabled) { - SegmentActions.setSegmentAsTagged( - currentSegment.sid, - currentSegment.id_file, - ) - } - }, - setSegmentAsTagged: function (sid, fid) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.SET_SEGMENT_TAGGED, - id: sid, - fid: fid, - }) - }, + disableTPOnSegment, + setSegmentAsTagged, - setSegmentWarnings: function (sid, warnings, tagMismatch) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.SET_SEGMENT_WARNINGS, - sid: sid, - warnings: warnings, - tagMismatch: tagMismatch, - }) - }, + setSegmentWarnings, - updateGlobalWarnings: function (warnings) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.UPDATE_GLOBAL_WARNINGS, - warnings: warnings, - }) - }, + updateGlobalWarnings, - qaComponentsetLxqIssues: function (issues) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.QA_LEXIQA_ISSUES, - warnings: issues, - }) - }, - setChoosenSuggestion: function (sid, index) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.SET_CHOOSEN_SUGGESTION, - sid: sid, - index: index, - }) - }, + qaComponentsetLxqIssues, + setChoosenSuggestion, addQaCheck: function (sid, data) { AppDispatcher.dispatch({ actionType: SegmentConstants.SET_QA_CHECK, @@ -554,14 +470,7 @@ const SegmentActions = { data, }) }, - addLexiqaHighlight: function (sid, matches, type) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.ADD_LXQ_HIGHLIGHT, - sid: sid, - matches: matches, - type: type, - }) - }, + addLexiqaHighlight, selectNextSegmentDebounced: debounce(() => { SegmentActions.selectNextSegment() }, 100), @@ -626,7 +535,7 @@ const SegmentActions = { } ModalsActions.showModalComponent( - CopySourceModal, + MODAL_KEY.COPY_SOURCE, props, 'Copy source to ALL segments', ) @@ -659,7 +568,7 @@ const SegmentActions = { position: 'bl', }), } - CatToolActions.addNotification(notification) + addNotification(notification) }) }, abortCopyAllSources: function () { @@ -680,7 +589,7 @@ const SegmentActions = { '

Re-Open Job

' } - CatToolActions.addNotification({ + addNotification({ uid: 'translate-warning', autoDismiss: false, dismissable: true, @@ -696,10 +605,10 @@ const SegmentActions = { const locked = !segment.unlocked && SegmentUtils.isIceSegment(segment) if (locked) { ModalsActions.showModalComponent( - AlertModal, + MODAL_KEY.ALERT, { text: - 'Segment is locked (in-context exact match) and shouldn’t be edited. ' + + "Segment is locked (in-context exact match) and shouldn't be edited. " + 'If you must edit it, click on the padlock icon to the left of the segment. ' + 'The owner of the project will be notified of any edits.', }, @@ -715,7 +624,7 @@ const SegmentActions = { if (isTranslationDisabled) { ModalsActions.showModalComponent( - AlertModal, + MODAL_KEY.ALERT, { text: "This segment has been disabled by the project owner, so it cannot be translated.", }, @@ -724,7 +633,7 @@ const SegmentActions = { return } - ModalsActions.showModalComponent(AlertModal, { + ModalsActions.showModalComponent(MODAL_KEY.ALERT, { text: SegmentActions.messageForClickOnReadonly(), }) }, @@ -740,20 +649,8 @@ const SegmentActions = { return 'This part has not been assigned to you.' }, /******************* EditArea ************/ - modifiedTranslation: function (sid, status) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.MODIFIED_TRANSLATION, - sid: sid, - status: status, - }) - }, - replaceEditAreaTextContent: function (sid, text) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.REPLACE_TRANSLATION, - id: sid, - translation: text, - }) - }, + modifiedTranslation, + replaceEditAreaTextContent, updateTranslation: function ( sid, @@ -832,13 +729,7 @@ const SegmentActions = { SegmentActions.replaceEditAreaTextContent(sid, translation) } }, - setSegmentSaving(sid, saving) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.SET_SEGMENT_SAVING, - sid, - saving, - }) - }, + setSegmentSaving, translateAndGoToNext: function () { const segment = SegmentStore.getCurrentSegment() if (!segment || SegmentUtils.isReadonlySegment(segment)) { @@ -864,7 +755,7 @@ const SegmentActions = { openSplitSegment: function (sid) { if (OfflineUtils.offline) { ModalsActions.showModalComponent( - AlertModal, + MODAL_KEY.ALERT, { text: 'Split is disabled in Offline Mode', }, @@ -891,14 +782,7 @@ const SegmentActions = { open: open, }) }, - setSegmentContributions: function (sid, contributions, errors) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.SET_CONTRIBUTIONS, - sid: sid, - matches: contributions, - errors: errors, - }) - }, + setSegmentContributions, setSegmentCrossLanguageContributions: function ( sid, fid, @@ -941,13 +825,7 @@ const SegmentActions = { }, ) }, - activateTab: function (sid, tab) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.OPEN_TAB, - sid: sid, - data: tab, - }) - }, + activateTab, closeTabs: function (sid) { AppDispatcher.dispatch({ actionType: SegmentConstants.CLOSE_TABS, @@ -1091,7 +969,7 @@ const SegmentActions = { type: 'warning', position: 'bl', } - CatToolActions.addNotification(notification) + addNotification(notification) } else { OfflineUtils.failedConnection() } @@ -1148,7 +1026,7 @@ const SegmentActions = { type: 'warning', position: 'bl', } - CatToolActions.addNotification(notification) + addNotification(notification) } else if (errors.length > 0) { AppDispatcher.dispatch({ actionType: SegmentConstants.SHOW_FOOTER_MESSAGE, @@ -1203,7 +1081,7 @@ const SegmentActions = { type: 'warning', position: 'bl', } - CatToolActions.addNotification(notification) + addNotification(notification) } else { OfflineUtils.failedConnection() } @@ -1453,7 +1331,11 @@ const SegmentActions = { ModalsActions.onCloseModal() }, } - ModalsActions.showModalComponent(ConfirmMessageModal, props, 'Warning') + ModalsActions.showModalComponent( + MODAL_KEY.CONFIRM_MESSAGE, + props, + 'Warning', + ) }, showTranslateAllModalWarnirng: function () { var props = { @@ -1463,7 +1345,11 @@ const SegmentActions = { ModalsActions.onCloseModal() }, } - ModalsActions.showModalComponent(ConfirmMessageModal, props, 'Warning') + ModalsActions.showModalComponent( + MODAL_KEY.CONFIRM_MESSAGE, + props, + 'Warning', + ) }, approveFilteredSegments: function (segmentsArray) { if (segmentsArray.length >= 100) { @@ -1566,10 +1452,10 @@ const SegmentActions = { SegmentStore.consecutiveUnlockSegments.push(segment.sid) if ( SegmentStore.consecutiveUnlockSegments.length >= 3 && - !localStorage.getItem(HIDE_UNLOCK_ALL_SEGMENTS_MODAL_STORAGE) + !localStorage.getItem('unlock-segments-modal' + config.id_job) ) { ModalsActions.showModalComponent( - UnlockAllSegmentsModal, + MODAL_KEY.UNLOCK_ALL_SEGMENTS, {}, 'Unlock all 101% segments', ) @@ -1601,17 +1487,8 @@ const SegmentActions = { segmentsArray: segmentsArray, }) }, - setMutedSegments(segmentsArray) { - AppDispatcher.dispatch({ - actionType: SegmentConstants.SET_MUTED_SEGMENTS, - segmentsArray: segmentsArray, - }) - }, - removeAllMutedSegments() { - AppDispatcher.dispatch({ - actionType: SegmentConstants.REMOVE_MUTED_SEGMENTS, - }) - }, + setMutedSegments, + removeAllMutedSegments, openSideSegments() { AppDispatcher.dispatch({ @@ -1639,11 +1516,13 @@ const SegmentActions = { }, gotoNextSegment() { if ( - SegmentsFilterUtil.enabled() && - SegmentsFilterUtil.filtering() && - SegmentsFilterUtil.open + getSegmentsFilterUtil().enabled() && + getSegmentsFilterUtil().filtering() && + getSegmentsFilterUtil().open ) { - SegmentsFilterUtil.gotoNextSegment(SegmentStore.getCurrentSegmentId()) + getSegmentsFilterUtil().gotoNextSegment( + SegmentStore.getCurrentSegmentId(), + ) } else { let next = SegmentStore.getNextSegment() if (next) { @@ -1666,11 +1545,11 @@ const SegmentActions = { // change this if we are filtering, go to the next // segment, assuming the sample is what we want to revise. if ( - SegmentsFilterUtil.enabled() && - SegmentsFilterUtil.filtering() && - SegmentsFilterUtil.open + getSegmentsFilterUtil().enabled() && + getSegmentsFilterUtil().filtering() && + getSegmentsFilterUtil().open ) { - SegmentsFilterUtil.gotoNextTranslatedSegment(sid) + getSegmentsFilterUtil().gotoNextTranslatedSegment(sid) } else { const nextTranslatedSegment = SegmentStore.getNextSegment({ current_sid: sid, @@ -1759,104 +1638,8 @@ const SegmentActions = { isFreezing, }) }, - getSegmentsQa: (segment) => { - if (!segment) return - - const {status, translation, updatedSource} = segment - - getLocalWarnings({ - id: segment.sid, - id_job: config.id_job, - password: config.password, - src_content: updatedSource, - trg_content: translation, - segment_status: status, - characters_counter: segment.charactersCounter ?? 0, - }) - .then((data) => { - if (data.details && data.details.id_segment) { - SegmentActions.setSegmentWarnings( - data.details.id_segment, - data.details.issues_info, - data.details.tag_mismatch, - ) - } else { - SegmentActions.setSegmentWarnings(segment.original_sid, {}, {}) - } - CommonUtils.dispatchCustomEvent('getWarning:local:success', { - resp: data, - segment: segment, - }) - }) - .catch(() => { - OfflineUtils.failedConnection() - }) - // get tm keys - new Promise((resolve) => { - if (!CatToolStore.getJobTmKeys() || !CatToolStore.getHaveKeysGlossary()) { - let isJobTmKeysCompleted = !!CatToolStore.getJobTmKeys() - let isHaveKeysGlossaryCompleted = !!CatToolStore.getHaveKeysGlossary() - - const resolvePromise = () => - isJobTmKeysCompleted && isHaveKeysGlossaryCompleted && resolve() - - const setJobTmKeys = () => { - isJobTmKeysCompleted = true - resolvePromise() - - CatToolStore.removeListener( - CatToolConstants.UPDATE_TM_KEYS, - setJobTmKeys, - ) - } - const setHaveKeysGlossary = () => { - isHaveKeysGlossaryCompleted = true - resolvePromise() - - CatToolStore.removeListener( - CatToolConstants.HAVE_KEYS_GLOSSARY, - setHaveKeysGlossary, - ) - } - - CatToolStore.addListener(CatToolConstants.UPDATE_TM_KEYS, setJobTmKeys) - CatToolStore.addListener( - CatToolConstants.HAVE_KEYS_GLOSSARY, - setHaveKeysGlossary, - ) - } else { - resolve() - } - }).then(() => { - const cleanSource = DraftMatecatUtils.removeTagsFromText(updatedSource) - const cleanTranslation = DraftMatecatUtils.removeTagsFromText(translation) - if ( - CatToolStore.getHaveKeysGlossary() && - cleanSource && - cleanTranslation - ) { - const jobTmKeys = CatToolStore.getJobTmKeys() - getGlossaryCheck({ - idSegment: segment.sid, - target: cleanTranslation, - source: cleanSource, - keys: jobTmKeys.map(({key}) => key), - }).catch((error) => { - console.log('Glossary check failed', error) - }) - } - }) - }, - highlightGlossaryTerm: ({sid, termId, type, isTarget}) => { - SegmentActions.activateTab(sid, 'glossary') - AppDispatcher.dispatch({ - actionType: SegmentConstants.HIGHLIGHT_GLOSSARY_TERM, - sid, - termId, - type, - isTarget, - }) - }, + getSegmentsQa, + highlightGlossaryTerm, helpAiAssistant: ({sid, value}) => { SegmentActions.modifyTabVisibility('AiAssistant', true) SegmentActions.activateTab(sid, 'AiAssistant') @@ -1899,7 +1682,7 @@ const SegmentActions = { }) }, setCurrentSegment: function (id_segment) { - CommonUtils.setLastSegmentFromLocalStorage(id_segment.toString()) + setLastSegmentFromLocalStorage(id_segment.toString()) const requestData = { action: 'setCurrentSegment', password: config.password, diff --git a/public/js/actions/SegmentActions.test.js b/public/js/actions/SegmentActions.test.js index 9f00089b74..cc9064286a 100644 --- a/public/js/actions/SegmentActions.test.js +++ b/public/js/actions/SegmentActions.test.js @@ -129,7 +129,6 @@ jest.mock('../utils/speech2text', () => ({ import SegmentActions from './SegmentActions' import SegmentUtils from '../utils/segmentUtils' import ModalsActions from './ModalsActions' -import AlertModal from '../components/modals/AlertModal' describe('SegmentActions.handleClickOnReadOnly', () => { beforeEach(() => { @@ -153,7 +152,7 @@ describe('SegmentActions.handleClickOnReadOnly', () => { SegmentActions.handleClickOnReadOnly(segment) expect(ModalsActions.showModalComponent).toHaveBeenCalledWith( - AlertModal, + 'Alert', { text: 'This segment has been disabled by the project owner, so it cannot be translated.', }, @@ -170,13 +169,13 @@ describe('SegmentActions.handleClickOnReadOnly', () => { SegmentActions.handleClickOnReadOnly(segment) expect(ModalsActions.showModalComponent).toHaveBeenCalledWith( - AlertModal, + 'Alert', expect.objectContaining({ text: expect.any(String), }), ) expect(ModalsActions.showModalComponent).not.toHaveBeenCalledWith( - AlertModal, + 'Alert', expect.objectContaining({ text: 'This segment has been disabled by the project owner, so it cannot be translated.', }), @@ -195,7 +194,7 @@ describe('SegmentActions.handleClickOnReadOnly', () => { SegmentActions.handleClickOnReadOnly(segment) expect(ModalsActions.showModalComponent).toHaveBeenCalledWith( - AlertModal, + 'Alert', expect.objectContaining({ text: expect.stringContaining('Segment is locked'), }), @@ -212,7 +211,7 @@ describe('SegmentActions.handleClickOnReadOnly', () => { SegmentActions.handleClickOnReadOnly(segment) expect(ModalsActions.showModalComponent).not.toHaveBeenCalledWith( - AlertModal, + 'Alert', expect.objectContaining({ text: 'This segment has been disabled by the project owner, so it cannot be translated.', }), diff --git a/public/js/actions/notificationActions.js b/public/js/actions/notificationActions.js new file mode 100644 index 0000000000..435a58a41b --- /dev/null +++ b/public/js/actions/notificationActions.js @@ -0,0 +1,22 @@ +import AppDispatcher from '../stores/AppDispatcher' +import CatToolConstants from '../constants/CatToolConstants' + +export const addNotification = (notification) => { + return AppDispatcher.dispatch({ + actionType: CatToolConstants.ADD_NOTIFICATION, + notification, + }) +} + +export const removeNotification = (notification) => { + AppDispatcher.dispatch({ + actionType: CatToolConstants.REMOVE_NOTIFICATION, + notification, + }) +} + +export const removeAllNotifications = () => { + AppDispatcher.dispatch({ + actionType: CatToolConstants.REMOVE_ALL_NOTIFICATION, + }) +} diff --git a/public/js/actions/segmentClassActions.js b/public/js/actions/segmentClassActions.js new file mode 100644 index 0000000000..f4fcd9a1db --- /dev/null +++ b/public/js/actions/segmentClassActions.js @@ -0,0 +1,24 @@ +import AppDispatcher from '../stores/AppDispatcher' +import SegmentConstants from '../constants/SegmentConstants' + +export const addClassToSegment = (sid, newClass) => { + setTimeout(function () { + AppDispatcher.dispatch({ + actionType: SegmentConstants.ADD_SEGMENT_CLASS, + id: sid, + newClass: newClass, + }) + }, 0) +} + +export const removeClassToSegment = (sid, className) => { + if (sid) { + setTimeout(function () { + AppDispatcher.dispatch({ + actionType: SegmentConstants.REMOVE_SEGMENT_CLASS, + id: sid, + className: className, + }) + }, 0) + } +} diff --git a/public/js/actions/segmentDispatchActions.js b/public/js/actions/segmentDispatchActions.js new file mode 100644 index 0000000000..bf622483c1 --- /dev/null +++ b/public/js/actions/segmentDispatchActions.js @@ -0,0 +1,169 @@ +import AppDispatcher from '../stores/AppDispatcher' +import SegmentConstants from '../constants/SegmentConstants' + +export const setStatus = (sid, fid, status) => { + if (sid) { + AppDispatcher.dispatch({ + actionType: SegmentConstants.SET_SEGMENT_STATUS, + id: sid, + fid: fid, + status: status, + }) + } +} + +export const setHeaderPercentage = (sid, fid, match, className, createdBy) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.SET_SEGMENT_HEADER, + id: sid, + fid: fid, + match, + className: className, + createdBy: createdBy, + }) +} + +export const hideSegmentHeader = (sid, fid) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.HIDE_SEGMENT_HEADER, + id: sid, + fid: fid, + }) +} + +export const setSegmentPropagation = (sid, fid, propagation, from) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.SET_SEGMENT_PROPAGATION, + id: sid, + fid: fid, + propagation: propagation, + from: from, + }) +} + +export const modifiedTranslation = (sid, status) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.MODIFIED_TRANSLATION, + sid: sid, + status: status, + }) +} + +export const replaceEditAreaTextContent = (sid, text) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.REPLACE_TRANSLATION, + id: sid, + translation: text, + }) +} + +export const setChoosenSuggestion = (sid, index) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.SET_CHOOSEN_SUGGESTION, + sid: sid, + index: index, + }) +} + +export const setSegmentContributions = (sid, contributions, errors) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.SET_CONTRIBUTIONS, + sid: sid, + matches: contributions, + errors: errors, + }) +} + +export const setSegmentSaving = (sid, saving) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.SET_SEGMENT_SAVING, + sid, + saving, + }) +} + +export const setMutedSegments = (segmentsArray) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.SET_MUTED_SEGMENTS, + segmentsArray: segmentsArray, + }) +} + +export const removeAllMutedSegments = () => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.REMOVE_MUTED_SEGMENTS, + }) +} + +export const activateTab = (sid, tab) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.OPEN_TAB, + sid: sid, + data: tab, + }) +} + +export const highlightGlossaryTerm = ({sid, termId, type, isTarget}) => { + activateTab(sid, 'glossary') + AppDispatcher.dispatch({ + actionType: SegmentConstants.HIGHLIGHT_GLOSSARY_TERM, + sid, + termId, + type, + isTarget, + }) +} + +export const addSearchResultToSegments = ( + occurrencesList, + searchResultsDictionary, + currentIndex, + text, +) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.ADD_SEARCH_RESULTS, + occurrencesList, + searchResultsDictionary, + currentIndex, + text, + }) +} + +export const removeSearchResultToSegments = () => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.REMOVE_SEARCH_RESULTS, + }) +} + +export const qaComponentsetLxqIssues = (issues) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.QA_LEXIQA_ISSUES, + warnings: issues, + }) +} + +export const addLexiqaHighlight = (sid, matches, type) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.ADD_LXQ_HIGHLIGHT, + sid: sid, + matches: matches, + type: type, + }) +} + +export const setSegmentWarnings = (sid, warnings, tagMismatch) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.SET_SEGMENT_WARNINGS, + sid: sid, + warnings: warnings, + tagMismatch: tagMismatch, + }) +} + +export const setSegmentAsTagged = (sid, fid) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.SET_SEGMENT_TAGGED, + id: sid, + fid: fid, + }) +} diff --git a/public/js/actions/segmentQaActions.js b/public/js/actions/segmentQaActions.js new file mode 100644 index 0000000000..caf09bb780 --- /dev/null +++ b/public/js/actions/segmentQaActions.js @@ -0,0 +1,107 @@ +import {getLocalWarnings} from '../api/getLocalWarnings' +import {getGlossaryCheck} from '../api/getGlossaryCheck' +import {removeTagsFromText} from '../components/segments/utils/DraftMatecatUtils/tagUtils' +import CommonUtils from '../utils/commonUtils' +import {setSegmentWarnings} from './segmentDispatchActions' +import CatToolConstants from '../constants/CatToolConstants' +import CatToolStore from '../stores/CatToolStore' +import OfflineUtils from '../utils/offlineUtils' +import SegmentStore from '../stores/SegmentStore' + +export const getSegmentsQa = (segment) => { + if (!segment) return + + const {status, translation, updatedSource} = segment + + getLocalWarnings({ + id: segment.sid, + id_job: config.id_job, + password: config.password, + src_content: updatedSource, + trg_content: translation, + segment_status: status, + characters_counter: segment.charactersCounter ?? 0, + }) + .then((data) => { + if (data.details && data.details.id_segment) { + setSegmentWarnings( + data.details.id_segment, + data.details.issues_info, + data.details.tag_mismatch, + ) + } else { + setSegmentWarnings(segment.original_sid, {}, {}) + } + CommonUtils.dispatchCustomEvent('getWarning:local:success', { + resp: data, + segment: segment, + }) + }) + .catch(() => { + OfflineUtils.failedConnection() + }) + // get tm keys + new Promise((resolve) => { + if (!CatToolStore.getJobTmKeys() || !CatToolStore.getHaveKeysGlossary()) { + let isJobTmKeysCompleted = !!CatToolStore.getJobTmKeys() + let isHaveKeysGlossaryCompleted = !!CatToolStore.getHaveKeysGlossary() + + const resolvePromise = () => + isJobTmKeysCompleted && isHaveKeysGlossaryCompleted && resolve() + + const setJobTmKeys = () => { + isJobTmKeysCompleted = true + resolvePromise() + + CatToolStore.removeListener( + CatToolConstants.UPDATE_TM_KEYS, + setJobTmKeys, + ) + } + const setHaveKeysGlossary = () => { + isHaveKeysGlossaryCompleted = true + resolvePromise() + + CatToolStore.removeListener( + CatToolConstants.HAVE_KEYS_GLOSSARY, + setHaveKeysGlossary, + ) + } + + CatToolStore.addListener(CatToolConstants.UPDATE_TM_KEYS, setJobTmKeys) + CatToolStore.addListener( + CatToolConstants.HAVE_KEYS_GLOSSARY, + setHaveKeysGlossary, + ) + } else { + resolve() + } + }).then(() => { + const cleanSource = removeTagsFromText(updatedSource) + const cleanTranslation = removeTagsFromText(translation) + if ( + CatToolStore.getHaveKeysGlossary() && + cleanSource && + cleanTranslation + ) { + const jobTmKeys = CatToolStore.getJobTmKeys() + getGlossaryCheck({ + idSegment: segment.sid, + target: cleanTranslation, + source: cleanSource, + keys: jobTmKeys.map(({key}) => key), + }).catch((error) => { + console.log('Glossary check failed', error) + }) + } + }) +} + +let pendingQACheck + +export const startSegmentQACheck = () => { + clearTimeout(pendingQACheck) + pendingQACheck = setTimeout(function () { + getSegmentsQa(SegmentStore.getCurrentSegment()) + }, config.segmentQACheckInterval) +} diff --git a/public/js/actions/tagProjectionActions.js b/public/js/actions/tagProjectionActions.js new file mode 100644 index 0000000000..bcdecf2bb8 --- /dev/null +++ b/public/js/actions/tagProjectionActions.js @@ -0,0 +1,18 @@ +import {hasDataOriginalTags} from '../components/segments/utils/DraftMatecatUtils/tagUtils' +import {setSegmentAsTagged} from './segmentDispatchActions' +import SegmentStore from '../stores/SegmentStore' +import {checkTPEnabled} from '../utils/tagProjectionUtils' + +export const disableTPOnSegment = (segmentObj) => { + var currentSegment = segmentObj + ? segmentObj + : SegmentStore.getCurrentSegment() + + if (!currentSegment) return + + var tagProjectionEnabled = + hasDataOriginalTags(currentSegment.segment) && !currentSegment.tagged + if (checkTPEnabled() && tagProjectionEnabled) { + setSegmentAsTagged(currentSegment.sid, currentSegment.id_file) + } +} diff --git a/public/js/actions/warningActions.js b/public/js/actions/warningActions.js new file mode 100644 index 0000000000..5fabd0e7fe --- /dev/null +++ b/public/js/actions/warningActions.js @@ -0,0 +1,9 @@ +import AppDispatcher from '../stores/AppDispatcher' +import SegmentConstants from '../constants/SegmentConstants' + +export const updateGlobalWarnings = (warnings) => { + AppDispatcher.dispatch({ + actionType: SegmentConstants.UPDATE_GLOBAL_WARNINGS, + warnings: warnings, + }) +} diff --git a/public/js/components/activityLog/ActivityLogConstants.js b/public/js/components/activityLog/ActivityLogConstants.js new file mode 100644 index 0000000000..b1678c1095 --- /dev/null +++ b/public/js/components/activityLog/ActivityLogConstants.js @@ -0,0 +1,10 @@ +export const ACTIVITY_LOG_COLUMNS = [ + {id: 'ip', label: 'User IP'}, + {id: 'event_date', label: 'Event Date', sortingType: 'date'}, + {id: 'id_project', label: 'Project ID'}, + {id: 'id_job', label: 'Job ID'}, + {id: 'languagePair', label: 'Language Pair'}, + {id: 'userName', label: 'User Name'}, + {id: 'email', label: 'User Email'}, + {id: 'action', label: 'Action'}, +] diff --git a/public/js/components/activityLog/ActivityLogContext.js b/public/js/components/activityLog/ActivityLogContext.js new file mode 100644 index 0000000000..c53eb66a59 --- /dev/null +++ b/public/js/components/activityLog/ActivityLogContext.js @@ -0,0 +1,3 @@ +import {createContext} from 'react' + +export const ActivityLogContext = createContext({}) diff --git a/public/js/components/activityLog/ActivityLogTable.js b/public/js/components/activityLog/ActivityLogTable.js index d407c801b7..eaa5df5acd 100644 --- a/public/js/components/activityLog/ActivityLogTable.js +++ b/public/js/components/activityLog/ActivityLogTable.js @@ -1,18 +1,9 @@ import React, {useContext, useState} from 'react' import {ColumnSorting} from './ColumnSorting' -import {ActivityLogContext} from '../../pages/ActivityLog' +import {ActivityLogContext} from './ActivityLogContext' import LabelWithTooltip from '../common/LabelWithTooltip' -export const ACTIVITY_LOG_COLUMNS = [ - {id: 'ip', label: 'User IP'}, - {id: 'event_date', label: 'Event Date', sortingType: 'date'}, - {id: 'id_project', label: 'Project ID'}, - {id: 'id_job', label: 'Job ID'}, - {id: 'languagePair', label: 'Language Pair'}, - {id: 'userName', label: 'User Name'}, - {id: 'email', label: 'User Email'}, - {id: 'action', label: 'Action'}, -] +import {ACTIVITY_LOG_COLUMNS} from './ActivityLogConstants' export const ActivityLogTable = () => { const {activityLog, filterByColumn} = useContext(ActivityLogContext) diff --git a/public/js/components/activityLog/ColumnSorting.js b/public/js/components/activityLog/ColumnSorting.js index 8bfeab64dd..e1e7fea5ed 100644 --- a/public/js/components/activityLog/ColumnSorting.js +++ b/public/js/components/activityLog/ColumnSorting.js @@ -1,6 +1,6 @@ import React, {useContext, useRef} from 'react' import PropTypes from 'prop-types' -import {ActivityLogContext} from '../../pages/ActivityLog' +import {ActivityLogContext} from './ActivityLogContext' import IconDown from '../icons/IconDown' export const ColumnSorting = ({ diff --git a/public/js/components/activityLog/FilterColumn.js b/public/js/components/activityLog/FilterColumn.js index 61a5445296..81ab253fac 100644 --- a/public/js/components/activityLog/FilterColumn.js +++ b/public/js/components/activityLog/FilterColumn.js @@ -1,7 +1,7 @@ import React, {useContext} from 'react' import {Select} from '../common/Select' -import {ACTIVITY_LOG_COLUMNS} from './ActivityLogTable' -import {ActivityLogContext} from '../../pages/ActivityLog' +import {ACTIVITY_LOG_COLUMNS} from './ActivityLogConstants' +import {ActivityLogContext} from './ActivityLogContext' export const FilterColumn = () => { const {filterByColumn, setFilterByColumn} = useContext(ActivityLogContext) diff --git a/public/js/components/createProject/UploadFile.js b/public/js/components/createProject/UploadFile.js index ea9c58c6ac..7db4303164 100644 --- a/public/js/components/createProject/UploadFile.js +++ b/public/js/components/createProject/UploadFile.js @@ -7,15 +7,7 @@ import {ApplicationWrapperContext} from '../common/ApplicationWrapper/Applicatio import {initFileUpload} from '../../api/initFileUpload' import {clearNotCompletedUploads} from '../../api/clearNotCompletedUploads' -export const getPrintableFileSize = (filesizeInBytes) => { - filesizeInBytes = filesizeInBytes / 1024 - let ext = ' KB' - if (filesizeInBytes > 1024) { - filesizeInBytes = filesizeInBytes / 1024 - ext = ' MB' - } - return Math.round(filesizeInBytes * 100, 2) / 100 + ext -} + export const UploadFile = ({...props}) => { const {openGDrive, currentProjectTemplate} = useContext(CreateProjectContext) const {isUserLogged} = useContext(ApplicationWrapperContext) diff --git a/public/js/components/createProject/UploadFileLocal.js b/public/js/components/createProject/UploadFileLocal.js index 1e906c0ce6..082fca0b10 100644 --- a/public/js/components/createProject/UploadFileLocal.js +++ b/public/js/components/createProject/UploadFileLocal.js @@ -1,12 +1,12 @@ import React, {useContext, useMemo} from 'react' import {Button, BUTTON_SIZE, BUTTON_TYPE} from '../common/Button/Button' -import {DeleteIcon} from '../segments/SegmentFooterTabGlossary' +import {DeleteIcon} from '../segments/SegmentFooterTabGlossary/GlossaryConstants' import FileUploadIconBig from '../../../img/icons/FileUploadIconBig' import CommonUtils from '../../utils/commonUtils' import IconAdd from '../icons/IconAdd' import IconClose from '../icons/IconClose' import {PROGRESS_BAR_SIZE, ProgressBar} from '../common/ProgressBar' -import {getPrintableFileSize} from './UploadFile' +import {getPrintableFileSize} from './UploadFileUtils' import {CreateProjectContext} from './CreateProjectContext' import {useFileUploadManager} from './hooks/useFileUploadManager' import {useDragAndDrop} from './hooks/useDragAndDrop' diff --git a/public/js/components/createProject/UploadFileUtils.js b/public/js/components/createProject/UploadFileUtils.js new file mode 100644 index 0000000000..a9d6cc5bf7 --- /dev/null +++ b/public/js/components/createProject/UploadFileUtils.js @@ -0,0 +1,9 @@ +export const getPrintableFileSize = (filesizeInBytes) => { + filesizeInBytes = filesizeInBytes / 1024 + let ext = ' KB' + if (filesizeInBytes > 1024) { + filesizeInBytes = filesizeInBytes / 1024 + ext = ' MB' + } + return Math.round(filesizeInBytes * 100) / 100 + ext +} diff --git a/public/js/components/createProject/UploadGdrive.js b/public/js/components/createProject/UploadGdrive.js index 4633febfdb..63836ce8f8 100644 --- a/public/js/components/createProject/UploadGdrive.js +++ b/public/js/components/createProject/UploadGdrive.js @@ -1,8 +1,8 @@ import React, {useContext, useEffect, useMemo} from 'react' import CommonUtils from '../../utils/commonUtils' -import {getPrintableFileSize} from './UploadFile' +import {getPrintableFileSize} from './UploadFileUtils' import {Button, BUTTON_SIZE, BUTTON_TYPE} from '../common/Button/Button' -import {DeleteIcon} from '../segments/SegmentFooterTabGlossary' +import {DeleteIcon} from '../segments/SegmentFooterTabGlossary/GlossaryConstants' import IconClose from '../icons/IconClose' import {usePrevious} from '../../hooks/usePrevious' import {CreateProjectContext} from './CreateProjectContext' diff --git a/public/js/components/header/cattol/search/searchUtils.js b/public/js/components/header/cattol/search/searchUtils.js index 994d8de9a4..5a70142b04 100644 --- a/public/js/components/header/cattol/search/searchUtils.js +++ b/public/js/components/header/cattol/search/searchUtils.js @@ -2,7 +2,10 @@ import {isUndefined, clone} from 'lodash' import {find} from 'lodash/collection' import {findIndex} from 'lodash/array' -import SegmentActions from '../../../../actions/SegmentActions' +import { + addSearchResultToSegments, + removeSearchResultToSegments, +} from '../../../../actions/segmentDispatchActions' import CatToolActions from '../../../../actions/CatToolActions' import SegmentStore from '../../../../stores/SegmentStore' import TextUtils from '../../../../utils/textUtils' @@ -148,7 +151,7 @@ let SearchUtils = { searchResultsDictionary: clone(this.searchResultsDictionary), featuredSearchResult: 0, }) - SegmentActions.addSearchResultToSegments( + addSearchResultToSegments( this.occurrencesList, this.searchResultsDictionary, 0, @@ -156,7 +159,7 @@ let SearchUtils = { ) console.log('this.searchResultsDictionary', this.searchResultsDictionary) } else { - SegmentActions.removeSearchResultToSegments() + removeSearchResultToSegments() this.resetSearch() CatToolActions.storeSearchResults({ total: 0, @@ -555,7 +558,7 @@ let SearchUtils = { this.searchResultsDictionary = {} this.featuredSearchResult = 0 this.searchSegmentsResult = [] - SegmentActions.removeSearchResultToSegments() + removeSearchResultToSegments() }, /** * Close search container @@ -563,7 +566,7 @@ let SearchUtils = { closeSearch: function () { this.resetSearch() CatToolActions.closeSubHeader() - SegmentActions.removeSearchResultToSegments() + removeSearchResultToSegments() CatToolActions.storeSearchResults({ total: 0, diff --git a/public/js/components/modals/CopySourceModal.js b/public/js/components/modals/CopySourceModal.js index aa0120f13d..c32f30c57e 100644 --- a/public/js/components/modals/CopySourceModal.js +++ b/public/js/components/modals/CopySourceModal.js @@ -7,7 +7,8 @@ import { BUTTON_SIZE, BUTTON_TYPE, } from '../common/Button/Button' -export const COPY_SOURCE_COOKIE = 'source_copied_to_target' +import {COPY_SOURCE_COOKIE} from '../../constants/ModalKeys' + class CopySourceModal extends React.Component { constructor(props) { super(props) diff --git a/public/js/components/modals/ModalWindow.js b/public/js/components/modals/ModalWindow.js index 62a16c73aa..7200fc4dfa 100644 --- a/public/js/components/modals/ModalWindow.js +++ b/public/js/components/modals/ModalWindow.js @@ -1,10 +1,10 @@ import React from 'react' -import {createRoot} from 'react-dom/client' import {ModalContainer} from './ModalContainer' import {ModalOverlay} from './ModalOverlay' import ModalsConstants from '../../constants/ModalsConstants' import CatToolStore from '../../stores/CatToolStore' +import {resolveModal} from './modalRegistry' const initialState = { isShowingModal: false, @@ -71,10 +71,11 @@ export class ModalWindow extends React.Component { styleBody, isCloseButtonDisabled, ) => { + const resolvedComponent = resolveModal(component) this.setState({ ...initialState, title, - component, + component: resolvedComponent, showHeader, compProps: { ...initialState.compProps, diff --git a/public/js/components/modals/modalRegistry.js b/public/js/components/modals/modalRegistry.js new file mode 100644 index 0000000000..03a74478bd --- /dev/null +++ b/public/js/components/modals/modalRegistry.js @@ -0,0 +1,39 @@ +import {MODAL_KEY} from '../../constants/ModalKeys' +import ConfirmMessageModal from './ConfirmMessageModal' +import SplitJobModal from './SplitJob' +import {CreateTeam} from './CreateTeam' +import {ModifyTeam} from './ModifyTeam' +import PreferencesModal from './PreferencesModal' +import SuccessModal from './SuccessModal' +import OnBoarding from '../onBoarding/OnBoarding' +import {DownloadAlertModal} from './DownloadAlertModal' +import AlertModal from './AlertModal' +import RevisionFeedbackModal from './RevisionFeedbackModal' +import CopySourceModal from './CopySourceModal' +import {UnlockAllSegmentsModal} from './UnlockAllSegmentsModal' + +const modalRegistry = { + [MODAL_KEY.CONFIRM_MESSAGE]: ConfirmMessageModal, + [MODAL_KEY.SPLIT_JOB]: SplitJobModal, + [MODAL_KEY.CREATE_TEAM]: CreateTeam, + [MODAL_KEY.MODIFY_TEAM]: ModifyTeam, + [MODAL_KEY.PREFERENCES]: PreferencesModal, + [MODAL_KEY.SUCCESS]: SuccessModal, + [MODAL_KEY.ONBOARDING]: OnBoarding, + [MODAL_KEY.DOWNLOAD_ALERT]: DownloadAlertModal, + [MODAL_KEY.ALERT]: AlertModal, + [MODAL_KEY.REVISION_FEEDBACK]: RevisionFeedbackModal, + [MODAL_KEY.COPY_SOURCE]: CopySourceModal, + [MODAL_KEY.UNLOCK_ALL_SEGMENTS]: UnlockAllSegmentsModal, +} + +export const resolveModal = (componentOrKey) => { + if (typeof componentOrKey === 'string') { + const resolved = modalRegistry[componentOrKey] + if (!resolved) { + console.error(`Unknown modal key: "${componentOrKey}"`) + } + return resolved + } + return componentOrKey +} diff --git a/public/js/components/onBoarding/ForgotPassword.js b/public/js/components/onBoarding/ForgotPassword.js index 844f871938..e9bfb32328 100644 --- a/public/js/components/onBoarding/ForgotPassword.js +++ b/public/js/components/onBoarding/ForgotPassword.js @@ -9,7 +9,8 @@ import { Button, } from '../common/Button/Button' import {forgotPassword} from '../../api/forgotPassword' -import {ONBOARDING_STEP, OnBoardingContext} from './OnBoarding' +import {ONBOARDING_STEP} from '../../constants/OnBoardingConstants' +import {OnBoardingContext} from './OnBoardingContext' const ForgotPassword = () => { const {setStep} = useContext(OnBoardingContext) diff --git a/public/js/components/onBoarding/Login.js b/public/js/components/onBoarding/Login.js index a6e84b398b..47789ccdbd 100644 --- a/public/js/components/onBoarding/Login.js +++ b/public/js/components/onBoarding/Login.js @@ -10,7 +10,8 @@ import SocialButtons from './SocialButtons' import {useForm, Controller} from 'react-hook-form' import {EMAIL_PATTERN} from '../../constants/Constants' import {Input, INPUT_TYPE} from '../common/Input/Input' -import {ONBOARDING_STEP, OnBoardingContext} from './OnBoarding' +import {ONBOARDING_STEP} from '../../constants/OnBoardingConstants' +import {OnBoardingContext} from './OnBoardingContext' import {loginUser} from '../../api/loginUser' const Login = () => { diff --git a/public/js/components/onBoarding/OnBoarding.js b/public/js/components/onBoarding/OnBoarding.js index 3715418896..e370f73a39 100644 --- a/public/js/components/onBoarding/OnBoarding.js +++ b/public/js/components/onBoarding/OnBoarding.js @@ -1,4 +1,4 @@ -import React, {createContext, useState} from 'react' +import React, {useState} from 'react' import PropTypes from 'prop-types' import Login from './Login' import Register from './Register' @@ -10,22 +10,9 @@ import ChevronDown from '../../../img/icons/ChevronDown' import ModalsActions from '../../actions/ModalsActions' import CommonUtils from '../../utils/commonUtils' -export const ONBOARDING_STEP = { - LOGIN: 'login', - REGISTER: 'register', - PASSWORD_RESET: 'passwordReset', - FORGOT_PASSWORD: 'forgotPassword', - SET_NEW_PASSWORD: 'setNewPassword', -} +import {ONBOARDING_STEP} from '../../constants/OnBoardingConstants' -export const OnBoardingContext = createContext({}) -export const socialUrls = { - googleUrl: config.googleAuthURL, - github: config.githubAuthUrl, - microsoft: config.microsoftAuthUrl, - linkedIn: config.linkedInAuthUrl, - meta: config.facebookAuthUrl, -} +import {OnBoardingContext} from './OnBoardingContext' const OnBoarding = ({ step = ONBOARDING_STEP.LOGIN, isCloseButtonEnabled = false, diff --git a/public/js/components/onBoarding/OnBoardingContext.js b/public/js/components/onBoarding/OnBoardingContext.js new file mode 100644 index 0000000000..bed979f372 --- /dev/null +++ b/public/js/components/onBoarding/OnBoardingContext.js @@ -0,0 +1,10 @@ +import {createContext} from 'react' + +export const OnBoardingContext = createContext({}) +export const socialUrls = { + googleUrl: config.googleAuthURL, + github: config.githubAuthUrl, + microsoft: config.microsoftAuthUrl, + linkedIn: config.linkedInAuthUrl, + meta: config.facebookAuthUrl, +} diff --git a/public/js/components/onBoarding/PasswordReset.js b/public/js/components/onBoarding/PasswordReset.js index f0aad9d2bf..4b4f7cbf01 100644 --- a/public/js/components/onBoarding/PasswordReset.js +++ b/public/js/components/onBoarding/PasswordReset.js @@ -8,7 +8,8 @@ import { Button, } from '../common/Button/Button' import {resetPasswordUser} from '../../api/resetPasswordUser' -import {ONBOARDING_STEP, OnBoardingContext} from './OnBoarding' +import {ONBOARDING_STEP} from '../../constants/OnBoardingConstants' +import {OnBoardingContext} from './OnBoardingContext' import {setNewUserPassword} from '../../api/setNewUserPassword' import ModalsActions from '../../actions/ModalsActions' diff --git a/public/js/components/onBoarding/Register.js b/public/js/components/onBoarding/Register.js index f622a0388d..ec973bd77e 100644 --- a/public/js/components/onBoarding/Register.js +++ b/public/js/components/onBoarding/Register.js @@ -10,7 +10,8 @@ import { BUTTON_TYPE, Button, } from '../common/Button/Button' -import {ONBOARDING_STEP, OnBoardingContext} from './OnBoarding' +import {ONBOARDING_STEP} from '../../constants/OnBoardingConstants' +import {OnBoardingContext} from './OnBoardingContext' import Checkmark from '../../../img/icons/Checkmark' import {registerUser} from '../../api/registerUser' import CommonUtils from '../../utils/commonUtils' diff --git a/public/js/components/onBoarding/SocialButtons.js b/public/js/components/onBoarding/SocialButtons.js index fc92dfc5bf..2b316991b4 100644 --- a/public/js/components/onBoarding/SocialButtons.js +++ b/public/js/components/onBoarding/SocialButtons.js @@ -1,6 +1,6 @@ import React, {useContext} from 'react' import {Button, BUTTON_SIZE} from '../common/Button/Button' -import {OnBoardingContext, socialUrls} from './OnBoarding' +import {OnBoardingContext, socialUrls} from './OnBoardingContext' const SocialButtons = () => { const {socialLogin} = useContext(OnBoardingContext) diff --git a/public/js/components/segments/GlossaryComponents/GlossaryHighlight.component.js b/public/js/components/segments/GlossaryComponents/GlossaryHighlight.component.js index b22f880fde..69f046a000 100644 --- a/public/js/components/segments/GlossaryComponents/GlossaryHighlight.component.js +++ b/public/js/components/segments/GlossaryComponents/GlossaryHighlight.component.js @@ -1,5 +1,5 @@ import React, {Component, createRef} from 'react' -import SegmentActions from '../../../actions/SegmentActions' +import {highlightGlossaryTerm} from '../../../actions/segmentDispatchActions' import Tooltip from '../../common/Tooltip' import TEXT_UTILS from '../../../utils/textUtils' import {tagSignatures} from '../utils/DraftMatecatUtils/tagModel' @@ -101,7 +101,7 @@ class GlossaryHighlight extends Component { const {sid} = this.props const glossaryTerm = this.getTermDetails() //Call Segment footer Action - SegmentActions.highlightGlossaryTerm({ + highlightGlossaryTerm({ sid, termId: glossaryTerm.term_id, type: 'glossary', diff --git a/public/js/components/segments/GlossaryComponents/QaCheckGlossaryHighlight.component.js b/public/js/components/segments/GlossaryComponents/QaCheckGlossaryHighlight.component.js index 9f3831f837..253aecad73 100644 --- a/public/js/components/segments/GlossaryComponents/QaCheckGlossaryHighlight.component.js +++ b/public/js/components/segments/GlossaryComponents/QaCheckGlossaryHighlight.component.js @@ -1,5 +1,5 @@ import React, {Component, createRef} from 'react' -import SegmentActions from '../../../actions/SegmentActions' +import {highlightGlossaryTerm} from '../../../actions/segmentDispatchActions' import Tooltip from '../../common/Tooltip' import {tagSignatures} from '../utils/DraftMatecatUtils/tagModel' import TEXT_UTILS from '../../../utils/textUtils' @@ -100,7 +100,7 @@ class QaCheckGlossaryHighlight extends Component { const glossaryTerm = this.getTermDetails() //Call Segment footer Action if (glossaryTerm) { - SegmentActions.highlightGlossaryTerm({ + highlightGlossaryTerm({ sid, termId: glossaryTerm.term_id, type: 'check', diff --git a/public/js/components/segments/SegmentFooter.js b/public/js/components/segments/SegmentFooter.js index 8309404146..091afd0515 100644 --- a/public/js/components/segments/SegmentFooter.js +++ b/public/js/components/segments/SegmentFooter.js @@ -28,19 +28,7 @@ import {SegmentFooterTabAiAlternatives} from './SegmentFooterTabAiAlternatives' import {SegmentFooterTabAiFeedback} from './SegmentFooterTabAiFeedback' import SegmentFooterTabIcu from './SegmentFooterTabIcu' -export const TAB = { - MATCHES: 'matches', - CONCORDANCES: 'concordances', - GLOSSARY: 'glossary', - ALTERNATIVES: 'alternatives', - MESSAGES: 'messages', - MULTIMATCHES: 'multiMatches', - AI_ASSISTANT: 'AiAssistant', - LARA_STYLES: 'laraStyles', - AI_ALTERNATIVES: 'aiAlternatives', - AI_FEEDBACK: 'aiFeedback', - ICU: 'icu', -} +import {TAB} from '../../constants/SegmentTabConstants' const TAB_ITEMS = { [TAB.MATCHES]: { diff --git a/public/js/components/segments/SegmentFooterTabGlossary/GlossaryConstants.js b/public/js/components/segments/SegmentFooterTabGlossary/GlossaryConstants.js new file mode 100644 index 0000000000..f72a1b0959 --- /dev/null +++ b/public/js/components/segments/SegmentFooterTabGlossary/GlossaryConstants.js @@ -0,0 +1,77 @@ +import React from 'react' + +export const TERM_FORM_FIELDS = { + DEFINITION: 'definition', + ORIGINAL_TERM: 'originalTerm', + ORIGINAL_DESCRIPTION: 'originalDescription', + ORIGINAL_EXAMPLE: 'originalExample', + TRANSLATED_TERM: 'translatedTerm', + TRANSLATED_DESCRIPTION: 'translatedDescription', + TRANSLATED_EXAMPLE: 'translatedExample', +} + +export const DeleteIcon = () => { + return ( + + + + ) +} + +export const ModifyIcon = () => { + return ( + + + + ) +} + +export const GlossaryDefinitionIcon = () => { + return ( + + + + ) +} + +export const MoreIcon = () => { + return ( + + + + ) +} + +export const LockIcon = () => { + return ( + + + + ) +} diff --git a/public/js/components/segments/SegmentFooterTabGlossary/GlossaryItem.js b/public/js/components/segments/SegmentFooterTabGlossary/GlossaryItem.js index c42831a82e..e6fe0ef364 100644 --- a/public/js/components/segments/SegmentFooterTabGlossary/GlossaryItem.js +++ b/public/js/components/segments/SegmentFooterTabGlossary/GlossaryItem.js @@ -7,7 +7,7 @@ import { GlossaryDefinitionIcon, LockIcon, ModifyIcon, -} from './SegmentFooterTabGlossary' +} from './GlossaryConstants' import {TabGlossaryContext} from './TabGlossaryContext' import LabelWithTooltip from '../../common/LabelWithTooltip' import Tooltip, {TOOLTIP_POSITION} from '../../common/Tooltip' diff --git a/public/js/components/segments/SegmentFooterTabGlossary/SegmentFooterTabGlossary.js b/public/js/components/segments/SegmentFooterTabGlossary/SegmentFooterTabGlossary.js index e7840b9c7a..654ae8bb10 100644 --- a/public/js/components/segments/SegmentFooterTabGlossary/SegmentFooterTabGlossary.js +++ b/public/js/components/segments/SegmentFooterTabGlossary/SegmentFooterTabGlossary.js @@ -23,15 +23,7 @@ import {checkMymemoryStatus} from '../../../api/checkMymemoryStatus' import AppDispatcher from '../../../stores/AppDispatcher' import {removeZeroWidthSpace} from '../utils/DraftMatecatUtils/tagUtils' -export const TERM_FORM_FIELDS = { - DEFINITION: 'definition', - ORIGINAL_TERM: 'originalTerm', - ORIGINAL_DESCRIPTION: 'originalDescription', - ORIGINAL_EXAMPLE: 'originalExample', - TRANSLATED_TERM: 'translatedTerm', - TRANSLATED_DESCRIPTION: 'translatedDescription', - TRANSLATED_EXAMPLE: 'translatedExample', -} +import {TERM_FORM_FIELDS} from './GlossaryConstants' const initialState = { keys: [], @@ -591,68 +583,3 @@ SegmentFooterTabGlossary.propTypes = { notifyLoadingStatus: PropTypes.func, } -export const DeleteIcon = () => { - return ( - - - - ) -} - -export const ModifyIcon = () => { - return ( - - - - ) -} - -export const GlossaryDefinitionIcon = () => { - return ( - - - - ) -} - -export const MoreIcon = () => { - return ( - - - - ) -} - -export const LockIcon = () => { - return ( - - - - ) -} diff --git a/public/js/components/segments/SegmentFooterTabGlossary/TermForm.js b/public/js/components/segments/SegmentFooterTabGlossary/TermForm.js index e3af2eabec..10efe60684 100644 --- a/public/js/components/segments/SegmentFooterTabGlossary/TermForm.js +++ b/public/js/components/segments/SegmentFooterTabGlossary/TermForm.js @@ -1,5 +1,5 @@ import React, {useCallback, useContext, useEffect, useState} from 'react' -import {MoreIcon, TERM_FORM_FIELDS} from './SegmentFooterTabGlossary' +import {MoreIcon, TERM_FORM_FIELDS} from './GlossaryConstants' import {TabGlossaryContext} from './TabGlossaryContext' import SegmentActions from '../../../actions/SegmentActions' import CatToolActions from '../../../actions/CatToolActions' diff --git a/public/js/components/segments/SegmentSource.js b/public/js/components/segments/SegmentSource.js index 63080aa6fc..8d91991014 100644 --- a/public/js/components/segments/SegmentSource.js +++ b/public/js/components/segments/SegmentSource.js @@ -18,7 +18,7 @@ import {tagSignatures} from './utils/DraftMatecatUtils/tagModel' import {SegmentContext} from './SegmentContext' import Assistant from '../icons/Assistant' import Education from '../icons/Education' -import {TERM_FORM_FIELDS} from './SegmentFooterTabGlossary' +import {TERM_FORM_FIELDS} from './SegmentFooterTabGlossary/GlossaryConstants' import {getEntitiesSelected} from './utils/DraftMatecatUtils/manageCaretPositionNearEntity' import { createICUDecorator, diff --git a/public/js/components/segments/utils/DraftMatecatUtils/decodeTagInfo.js b/public/js/components/segments/utils/DraftMatecatUtils/decodeTagInfo.js index 24c321908a..191d37501c 100644 --- a/public/js/components/segments/utils/DraftMatecatUtils/decodeTagInfo.js +++ b/public/js/components/segments/utils/DraftMatecatUtils/decodeTagInfo.js @@ -1,5 +1,5 @@ import {tagSignatures} from './tagModel' -import {getIdAttributeRegEx, unescapeHTMLRecursive} from './tagUtils' +import {getIdAttributeRegEx, unescapeHTMLRecursive} from './htmlUtils' import {Base64} from 'js-base64' /** diff --git a/public/js/components/segments/utils/DraftMatecatUtils/htmlUtils.js b/public/js/components/segments/utils/DraftMatecatUtils/htmlUtils.js new file mode 100644 index 0000000000..152b2e6d7f --- /dev/null +++ b/public/js/components/segments/utils/DraftMatecatUtils/htmlUtils.js @@ -0,0 +1,32 @@ +export const getIdAttributeRegEx = () => { + return /id="(-?\w+)"/g +} + +export const unescapeHTMLinTags = (escapedHTML) => { + try { + return escapedHTML + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&amp;/g, '&') + .replace(/&/g, '&') + .replace(/ /g, ' ') + .replace(/'/g, "'") + .replace(/"/g, '"') + } catch (e) { + return '' + } +} + +export const unescapeHTMLRecursive = (escapedHTML) => { + const regex = /&|<|>| |'|"/ + + try { + while (regex.exec(escapedHTML) !== null) { + escapedHTML = unescapeHTMLinTags(escapedHTML) + } + } catch (e) { + console.error('Error unescapeHTMLRecursive') + } + + return escapedHTML +} diff --git a/public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js b/public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js index 67d597a687..e6ec6ab93f 100644 --- a/public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js +++ b/public/js/components/segments/utils/DraftMatecatUtils/tagUtils.js @@ -4,7 +4,32 @@ import { tagSignatures, } from './tagModel' import {Base64} from 'js-base64' -import TextUtils from '../../../../utils/textUtils' +// replaceTempTags/restoreTempTags inlined from textUtils to avoid +// the cycle: SegmentStore → tagUtils → textUtils → commonUtils → SegmentStore +const replaceTempTags = (text) => { + const tags = [] + const makeid = (len) => { + let r = '' + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + for (let i = 0; i < len; i++) + r += chars.charAt(Math.floor(Math.random() * chars.length)) + return r + } + text = text.replace( + /<(\/)*(g|x|bx|ex|bpt|ept|ph|it|mrk).*?>/gi, + (match) => { + const id = makeid(5) + tags.push({id, match}) + return '#_' + id + '_#' + }, + ) + return {tags, text} +} +const restoreTempTags = (tags, text) => + text.replace(/#_([a-zA-Z]+?)_#/gi, (match, id) => { + const tag = tags.find((item) => item.id === id) + return tag ? tag.match : match + }) import {isUndefined} from 'lodash' import getEntities from './getEntities' import matchTagStructure from './matchTag' @@ -155,9 +180,9 @@ export const transformTagsToLexiqaText = (text) => { ) let textNormalized = text - const {tags, text: tempText} = TextUtils.replaceTempTags(text) + const {tags, text: tempText} = replaceTempTags(text) textNormalized = decodeHtmlEntities(tempText) - textNormalized = TextUtils.restoreTempTags(tags, textNormalized) + textNormalized = restoreTempTags(tags, textNormalized) return tagsStruct.reduce( (acc, {data}) => { @@ -363,15 +388,7 @@ export const encodeHtmlEntities = (text) => { // .replace(/'/g, ''') } -export const getIdAttributeRegEx = () => { - return /id="(-?\w+)"/g -} -/** - * - * @param segmentString - * @returns {*} - */ export const removeTagsFromText = (segmentString) => { const regExp = getXliffRegExpression() if (segmentString) { @@ -380,13 +397,6 @@ export const removeTagsFromText = (segmentString) => { return segmentString } -/** - * Checks if the given segment string contains XLIFF tags. - * - * @param {string} segmentString - The segment string to check for XLIFF tags. - * @returns {boolean|string} - Returns `true` if XLIFF tags are found, `false` if not, - * or the original segment string if it is empty. - */ export const textHasTags = (segmentString) => { const regExp = getXliffRegExpression() if (segmentString) { @@ -395,40 +405,6 @@ export const textHasTags = (segmentString) => { return segmentString } -/** - * - * @param escapedHTML - * @returns {string} - */ -export const unescapeHTMLinTags = (escapedHTML) => { - try { - return escapedHTML - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/&amp;/g, '&') - .replace(/&/g, '&') - .replace(/ /g, ' ') - .replace(/'/g, "'") - .replace(/"/g, '"') - } catch (e) { - return '' - } -} - -export const unescapeHTMLRecursive = (escapedHTML) => { - const regex = /&|<|>| |'|"/ - - try { - while (regex.exec(escapedHTML) !== null) { - escapedHTML = unescapeHTMLinTags(escapedHTML) - } - } catch (e) { - console.error('Error unescapeHTMLRecursive') - } - - return escapedHTML -} - /** * Add at the end of the target the missing tags */ diff --git a/public/js/components/segments/utils/DraftMatecatUtils/textConstants.js b/public/js/components/segments/utils/DraftMatecatUtils/textConstants.js new file mode 100644 index 0000000000..152b678d73 --- /dev/null +++ b/public/js/components/segments/utils/DraftMatecatUtils/textConstants.js @@ -0,0 +1,2 @@ +export const regexWordDelimiter = + /(\s+|[-+*\\/]|\d+|[!@#$%^&*()_+\-=\\[\]{};':"\\|,.<>\\/?~°⇥])/ diff --git a/public/js/components/segments/utils/DraftMatecatUtils/textUtils.js b/public/js/components/segments/utils/DraftMatecatUtils/textUtils.js index 1cf86cadfa..3279ccfd42 100644 --- a/public/js/components/segments/utils/DraftMatecatUtils/textUtils.js +++ b/public/js/components/segments/utils/DraftMatecatUtils/textUtils.js @@ -68,8 +68,7 @@ export const formatText = (text, format) => { return text } -export const regexWordDelimiter = - /(\s+|[-+*\\/]|\d+|[!@#$%^&*()_+\-=\\[\]{};':"\\|,.<>\\/?~°⇥])/ + export const getCharactersCounter = (value) => { let cleanedContent = TEXT_UTILS.removeHiddenCharacters( diff --git a/public/js/components/segments/utils/translationMatches.js b/public/js/components/segments/utils/translationMatches.js index 537d14d6f1..4b0ab9c066 100644 --- a/public/js/components/segments/utils/translationMatches.js +++ b/public/js/components/segments/utils/translationMatches.js @@ -6,7 +6,19 @@ import CommonUtils from '../../../utils/commonUtils' import OfflineUtils from '../../../utils/offlineUtils' import Speech2Text from '../../../utils/speech2text' import DraftMatecatUtils from './DraftMatecatUtils' -import SegmentActions from '../../../actions/SegmentActions' +import {addClassToSegment} from '../../../actions/segmentClassActions' +import { + replaceEditAreaTextContent, + setHeaderPercentage, + modifiedTranslation, + setSegmentContributions, + setChoosenSuggestion, +} from '../../../actions/segmentDispatchActions' +import { + getSegmentsQa, + startSegmentQACheck, +} from '../../../actions/segmentQaActions' +import {disableTPOnSegment} from '../../../actions/tagProjectionActions' import SegmentStore from '../../../stores/SegmentStore' import {getContributions} from '../../../api/getContributions' import {deleteContribution} from '../../../api/deleteContribution' @@ -28,21 +40,21 @@ let TranslationMatches = { translation = translation ? translation : matchToUse.translation var percentageClass = this.getPercentageClass(matchToUse) if ($.trim(translation) !== '') { - SegmentActions.replaceEditAreaTextContent(segment.sid, translation) - SegmentActions.setHeaderPercentage( + replaceEditAreaTextContent(segment.sid, translation) + setHeaderPercentage( segment.sid, segment.id_file, matchToUse, percentageClass, matchToUse.created_by, ) - SegmentActions.startSegmentQACheck() + startSegmentQACheck() CommonUtils.dispatchCustomEvent('contribution:copied', { translation: translation, segment: segment, }) - SegmentActions.modifiedTranslation( + modifiedTranslation( segment.sid, segment.translation !== '', ) @@ -54,7 +66,7 @@ let TranslationMatches = { var segmentObj = SegmentStore.getSegmentByIdToJS(sid) if (isUndefined(segmentObj)) return - SegmentActions.setSegmentContributions( + setSegmentContributions( segmentObj.sid, data.matches, data.errors, @@ -62,7 +74,7 @@ let TranslationMatches = { this.useSuggestionInEditArea(sid) - SegmentActions.addClassToSegment(sid, 'loaded') + addClassToSegment(sid, 'loaded') }, useSuggestionInEditArea: function (sid) { let segmentObj = SegmentStore.getSegmentByIdToJS(sid) @@ -80,7 +92,7 @@ let TranslationMatches = { var translation = matches[0].translation if (editareaLength === 0) { - SegmentActions.setChoosenSuggestion(segmentObj.sid, 1) + setChoosenSuggestion(segmentObj.sid, 1) /*If Tag Projection is enable and the current contribution is 100% match I leave the tags and replace * the source with the text with tags, the segment is tagged @@ -91,7 +103,7 @@ let TranslationMatches = { if (parseInt(match) !== 100) { translation = DraftMatecatUtils.removeTagsFromText(translation) } else { - SegmentActions.disableTPOnSegment(segmentObj) + disableTPOnSegment(segmentObj) } } @@ -194,8 +206,8 @@ let TranslationMatches = { const currentSegment = SegmentStore.getSegmentByIdToJS(sid) if (!currentSegment) return Promise.resolve() if (!config.translation_matches_enabled) { - SegmentActions.addClassToSegment(currentSegment.sid, 'loaded') - SegmentActions.getSegmentsQa(currentSegment) + addClassToSegment(currentSegment.sid, 'loaded') + getSegmentsQa(currentSegment) return Promise.resolve() } @@ -368,7 +380,7 @@ let TranslationMatches = { }, renderContributionErrors: function (errors, segmentId) { - SegmentActions.setSegmentContributions(segmentId, [], errors) + setSegmentContributions(segmentId, [], errors) }, setDeleteSuggestion: function (source, target, id, sid) { diff --git a/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTab.js b/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTab.js index c0e2e541bb..dcce0fe544 100644 --- a/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTab.js +++ b/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTab.js @@ -15,6 +15,7 @@ import {SCHEMA_KEYS} from '../../../../hooks/useProjectTemplates' import CatToolActions from '../../../../actions/CatToolActions' import ModalsActions from '../../../../actions/ModalsActions' import {ConfirmDeleteResourceProjectTemplates} from '../../../modals/ConfirmDeleteResourceProjectTemplates' +import {ANALYSIS_BREAKDOWNS} from './AnalysisTabConstants' export const ANALYSIS_SCHEMA_KEYS = { id: 'id', @@ -26,19 +27,7 @@ export const ANALYSIS_SCHEMA_KEYS = { deletedAt: 'deletedAt', version: 'version', } -export const ANALYSIS_BREAKDOWNS = { - newWords: 'NO_MATCH', - tm50_74: '50%-74%', - tm75_84: '75%-84%', - tm85_94: '85%-94%', - tm95_99: '95%-99%', - tm100: '100%', - public100: '100%_PUBLIC', - repetitions: 'REPETITIONS', - internal75_99: 'INTERNAL', - mt: 'MT', - tm100InContext: 'ICE', -} + const getFilteredSchemaCreateUpdate = (template) => { /* eslint-disable no-unused-vars */ diff --git a/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTab.test.js b/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTab.test.js index dfb5229de8..db14d8616d 100644 --- a/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTab.test.js +++ b/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTab.test.js @@ -7,11 +7,8 @@ import { waitFor, } from '@testing-library/react' import {SettingsPanelContext} from '../../SettingsPanelContext' -import { - ANALYSIS_BREAKDOWNS, - ANALYSIS_SCHEMA_KEYS, - AnalysisTab, -} from './AnalysisTab' +import {ANALYSIS_SCHEMA_KEYS, AnalysisTab} from './AnalysisTab' +import {ANALYSIS_BREAKDOWNS} from './AnalysisTabConstants' import projectTemplatesMock from '../../../../../mocks/projectTemplateMock' import {mswServer} from '../../../../../mocks/mswServer' import {http, HttpResponse} from 'msw' diff --git a/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTabConstants.js b/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTabConstants.js new file mode 100644 index 0000000000..119dacdd48 --- /dev/null +++ b/public/js/components/settingsPanel/Contents/AnalysisTab/AnalysisTabConstants.js @@ -0,0 +1,13 @@ +export const ANALYSIS_BREAKDOWNS = { + newWords: 'NO_MATCH', + tm50_74: '50%-74%', + tm75_84: '75%-84%', + tm85_94: '85%-94%', + tm95_99: '95%-99%', + tm100: '100%', + public100: '100%_PUBLIC', + repetitions: 'REPETITIONS', + internal75_99: 'INTERNAL', + mt: 'MT', + tm100InContext: 'ICE', +} diff --git a/public/js/components/settingsPanel/Contents/AnalysisTab/BreakdownsTable.js b/public/js/components/settingsPanel/Contents/AnalysisTab/BreakdownsTable.js index 0d03e0ac69..7b17aae760 100644 --- a/public/js/components/settingsPanel/Contents/AnalysisTab/BreakdownsTable.js +++ b/public/js/components/settingsPanel/Contents/AnalysisTab/BreakdownsTable.js @@ -1,6 +1,6 @@ import React, {useContext} from 'react' import {InputPercentage} from './InputPercentage' -import {ANALYSIS_BREAKDOWNS} from './AnalysisTab' +import {ANALYSIS_BREAKDOWNS} from './AnalysisTabConstants' import {SettingsPanelContext} from '../../SettingsPanelContext' export const BreakdownsTable = ({saveValue}) => { diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/AccordionGroupFiltersParams.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/AccordionGroupFiltersParams.js index 12a9a49e1f..67f6ce3bda 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/AccordionGroupFiltersParams.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/AccordionGroupFiltersParams.js @@ -7,7 +7,7 @@ import {MsWord} from './MsWord' import {MsPowerpoint} from './MsPowerpoint' import {MsExcel} from './MsExcel' import {Dita} from './Dita' -import {FiltersParamsContext} from './FiltersParams' +import {FiltersParamsContext} from './FiltersParamsContext' import {isEqual} from 'lodash' const ACCORDION_GROUP = { diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Dita.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Dita.js index b240b5412f..0d84288e30 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Dita.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Dita.js @@ -1,5 +1,5 @@ import React, {useContext, useEffect, useRef, useState} from 'react' -import {FiltersParamsContext} from './FiltersParams' +import {FiltersParamsContext} from './FiltersParamsContext' import {Controller, useForm} from 'react-hook-form' import {isEqual} from 'lodash' import {WordsBadge} from '../../../../common/WordsBadge/WordsBadge' diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/FiltersParams.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/FiltersParams.js index 240dbb7560..1f0ec1280b 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/FiltersParams.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/FiltersParams.js @@ -62,7 +62,7 @@ const getFilteredSchemaToCompare = (template) => { /* eslint-enable no-unused-vars */ } -export const FiltersParamsContext = createContext({}) +import {FiltersParamsContext} from './FiltersParamsContext' export const FiltersParams = () => { const { diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/FiltersParamsContext.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/FiltersParamsContext.js new file mode 100644 index 0000000000..71284e2a78 --- /dev/null +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/FiltersParamsContext.js @@ -0,0 +1,3 @@ +import {createContext} from 'react' + +export const FiltersParamsContext = createContext({}) diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Json.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Json.js index f1e4c49249..1556e30b2c 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Json.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Json.js @@ -2,7 +2,7 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import Switch from '../../../../common/Switch' import {SegmentedControl} from '../../../../common/SegmentedControl' import {WordsBadge} from '../../../../common/WordsBadge/WordsBadge' -import {FiltersParamsContext} from './FiltersParams' +import {FiltersParamsContext} from './FiltersParamsContext' import {Controller, useForm} from 'react-hook-form' import {isEqual} from 'lodash' diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsExcel.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsExcel.js index 7f1a691832..cb028f9787 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsExcel.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsExcel.js @@ -1,6 +1,6 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import Switch from '../../../../common/Switch' -import {FiltersParamsContext} from './FiltersParams' +import {FiltersParamsContext} from './FiltersParamsContext' import {Controller, useForm} from 'react-hook-form' import {isEqual} from 'lodash' import {WordsBadge} from '../../../../common/WordsBadge/WordsBadge' diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsPowerpoint.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsPowerpoint.js index 6b5c13f885..53555f2106 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsPowerpoint.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsPowerpoint.js @@ -1,6 +1,6 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import Switch from '../../../../common/Switch' -import {FiltersParamsContext} from './FiltersParams' +import {FiltersParamsContext} from './FiltersParamsContext' import {Controller, useForm} from 'react-hook-form' import {isEqual} from 'lodash' import {NumbersDashBadge} from './NumbersDashBadge' diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsWord.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsWord.js index 8f63bea127..1c4c6b335f 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsWord.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/MsWord.js @@ -1,7 +1,7 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import Switch from '../../../../common/Switch' import {WordsBadge} from '../../../../common/WordsBadge/WordsBadge' -import {FiltersParamsContext} from './FiltersParams' +import {FiltersParamsContext} from './FiltersParamsContext' import {Controller, useForm} from 'react-hook-form' import {isEqual} from 'lodash' diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Xml.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Xml.js index 8219355c5e..c164b7742b 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Xml.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Xml.js @@ -2,7 +2,7 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import Switch from '../../../../common/Switch' import {SegmentedControl} from '../../../../common/SegmentedControl' import {WordsBadge} from '../../../../common/WordsBadge/WordsBadge' -import {FiltersParamsContext} from './FiltersParams' +import {FiltersParamsContext} from './FiltersParamsContext' import {Controller, useForm} from 'react-hook-form' import {isEqual} from 'lodash' diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Yaml.js b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Yaml.js index f1041ba74c..2a2168d22d 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Yaml.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/FiltersParams/Yaml.js @@ -1,7 +1,7 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import {SegmentedControl} from '../../../../common/SegmentedControl' import {WordsBadge} from '../../../../common/WordsBadge/WordsBadge' -import {FiltersParamsContext} from './FiltersParams' +import {FiltersParamsContext} from './FiltersParamsContext' import {Controller, useForm} from 'react-hook-form' import {isEqual} from 'lodash' import {Select} from '../../../../common/Select' diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/Xliff12.js b/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/Xliff12.js index a6210a51d9..51f5914e70 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/Xliff12.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/Xliff12.js @@ -1,5 +1,5 @@ import React, {useCallback, useContext, useMemo, useState} from 'react' -import {XliffSettingsContext} from './XliffSettings' +import {XliffSettingsContext} from './XliffSettingsContext' import {XliffRulesRow} from './XliffRulesRow' import {Accordion} from '../../../../common/Accordion/Accordion' import xliffOptions from '../../defaultTemplates/xliffOptions.json' diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/Xliff20.js b/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/Xliff20.js index 6831d2a415..4dd8a200d0 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/Xliff20.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/Xliff20.js @@ -1,5 +1,5 @@ import React, {useCallback, useContext, useMemo, useState} from 'react' -import {XliffSettingsContext} from './XliffSettings' +import {XliffSettingsContext} from './XliffSettingsContext' import {XliffRulesRow} from './XliffRulesRow' import {Accordion} from '../../../../common/Accordion/Accordion' import xliffOptions from '../../defaultTemplates/xliffOptions.json' diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/XliffSettings.js b/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/XliffSettings.js index 1019c78def..fdc0d4f2af 100644 --- a/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/XliffSettings.js +++ b/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/XliffSettings.js @@ -53,7 +53,7 @@ const getFilteredSchemaToCompare = (template) => { /* eslint-enable no-unused-vars */ } -export const XliffSettingsContext = createContext({}) +import {XliffSettingsContext} from './XliffSettingsContext' export const XliffSettings = () => { const { diff --git a/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/XliffSettingsContext.js b/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/XliffSettingsContext.js new file mode 100644 index 0000000000..53bb925527 --- /dev/null +++ b/public/js/components/settingsPanel/Contents/FileImportTab/XliffSettings/XliffSettingsContext.js @@ -0,0 +1,3 @@ +import {createContext} from 'react' + +export const XliffSettingsContext = createContext({}) diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossary.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossary.js index 37caa010a8..44e8378951 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossary.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossary.js @@ -17,6 +17,7 @@ import ModalsActions from '../../../../../actions/ModalsActions' import {ConfirmDeleteResourceProjectTemplates} from '../../../../modals/ConfirmDeleteResourceProjectTemplates' import {SCHEMA_KEYS} from '../../../../../hooks/useProjectTemplates' import {DeepLGlossaryNoneRow} from './DeepLGlossaryNoneRow' +import {DEEPL_GLOSSARY_CREATE_ROW_ID} from './DeepLGlossaryConstants' const COLUMNS_TABLE = [ {name: 'Active'}, @@ -25,7 +26,7 @@ const COLUMNS_TABLE = [ {name: ''}, ] -export const DEEPL_GLOSSARY_CREATE_ROW_ID = 'createRow' + export const DEEPL_GLOSSARY_ROW_NONE = '' export const DeepLGlossary = ({id, setGlossaries, isCattoolPage = false}) => { diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryConstants.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryConstants.js new file mode 100644 index 0000000000..9536adcc90 --- /dev/null +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryConstants.js @@ -0,0 +1 @@ +export const DEEPL_GLOSSARY_CREATE_ROW_ID = 'createRow' diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryCreateRow.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryCreateRow.js index 71d28ce1ef..55805e930c 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryCreateRow.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryCreateRow.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import Upload from '../../../../../../img/icons/Upload' import Checkmark from '../../../../../../img/icons/Checkmark' import Close from '../../../../../../img/icons/Close' -import {DEEPL_GLOSSARY_CREATE_ROW_ID} from './DeepLGlossary' +import {DEEPL_GLOSSARY_CREATE_ROW_ID} from './DeepLGlossaryConstants' import {createAndImportDeepLGlossary} from '../../../../../api/createAndImportDeepLGlossary' import LabelWithTooltip from '../../../../common/LabelWithTooltip' import CatToolActions from '../../../../../actions/CatToolActions' diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryConstants.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryConstants.js new file mode 100644 index 0000000000..b298c4490b --- /dev/null +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryConstants.js @@ -0,0 +1,39 @@ +import {getStatusMemoryGlossaryImport} from '../../../../../api/getStatusMemoryGlossaryImport/getStatusMemoryGlossaryImport' + +export const MT_GLOSSARY_CREATE_ROW_ID = 'createRow' + +export class MTGlossaryStatus { + constructor() { + this.wasAborted = false + } + + get(props, promise = getStatusMemoryGlossaryImport) { + this.wasAborted = false + return new Promise((resolve, reject) => { + this.executeApi({promise, props, resolve, reject}) + }) + } + + cancel() { + this.wasAborted = true + } + + executeApi({promise, props, resolve, reject}) { + const DELAY = 1000 + + promise(props).then((data) => { + if (typeof data?.progress === 'undefined') { + reject() + return + } + if (data.progress === 0) { + setTimeout(() => { + if (!this.wasAborted) + this.executeApi({promise, props, resolve, reject}) + }, DELAY) + } else { + resolve(data) + } + }) + } +} diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryCreateRow.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryCreateRow.js index f849e6c1fc..b48203bf47 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryCreateRow.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryCreateRow.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import Upload from '../../../../../../img/icons/Upload' import Checkmark from '../../../../../../img/icons/Checkmark' import Close from '../../../../../../img/icons/Close' -import {MTGlossaryStatus, MT_GLOSSARY_CREATE_ROW_ID} from './MTGlossary' +import {MTGlossaryStatus, MT_GLOSSARY_CREATE_ROW_ID} from './MTGlossaryConstants' import {createMemoryAndImportGlossary} from '../../../../../api/createMemoryAndImportGlossary/createMemoryAndImportGlossary' import LabelWithTooltip from '../../../../common/LabelWithTooltip' import CatToolActions from '../../../../../actions/CatToolActions' diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryRow.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryRow.js index 73f3d9c167..0fa6418b1f 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryRow.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryRow.js @@ -9,7 +9,7 @@ import React, { import PropTypes from 'prop-types' import Upload from '../../../../../../img/icons/Upload' import Trash from '../../../../../../img/icons/Trash' -import {MTGlossaryStatus} from './MTGlossary' +import {MTGlossaryStatus} from './MTGlossaryConstants' import {importMemoryGlossary} from '../../../../../api/importMemoryGlossary/importMemoryGlossary' import {updateMemoryGlossary} from '../../../../../api/updateMemoryGlossary/updateMemoryGlossary' import IconEdit from '../../../../icons/IconEdit' diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.js index 4f060ae8f9..6291b09854 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.js @@ -12,7 +12,7 @@ import {SettingsPanelTable} from '../../SettingsPanelTable' import {MTRow} from './MTRow' import {SettingsPanelContext} from '../../SettingsPanelContext' import {deleteMTEngine} from '../../../../api/deleteMTEngine' -import {DEFAULT_ENGINE_MEMORY} from '../../SettingsPanel' +import {DEFAULT_ENGINE_MEMORY} from '../../SettingsPanelConstants' import {DeepL} from './MtEngines/DeepL' import CreateProjectActions from '../../../../actions/CreateProjectActions' diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddCategory.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddCategory.js index bc49c9e713..65441afeee 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddCategory.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddCategory.js @@ -10,14 +10,14 @@ import { BUTTON_TYPE, Button, } from '../../../common/Button/Button' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' import IconAdd from '../../../icons/IconAdd' import Checkmark from '../../../../../img/icons/Checkmark' import { getCodeFromLabel, formatCategoryDescription, getCategoryLabelAndDescription, -} from './CategoriesSeveritiesTable' +} from './CategoriesSeveritiesTableUtils' import {TOOLTIP_POSITION} from '../../../common/Tooltip' const MAX_ENTRY = 50 diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddSeverity.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddSeverity.js index d33312c186..890b4c4b4e 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddSeverity.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddSeverity.js @@ -10,10 +10,10 @@ import { BUTTON_SIZE, BUTTON_TYPE, } from '../../../common/Button/Button' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' import IconAdd from '../../../icons/IconAdd' import Checkmark from '../../../../../img/icons/Checkmark' -import {getCodeFromLabel} from './CategoriesSeveritiesTable' +import {getCodeFromLabel} from './CategoriesSeveritiesTableUtils' import {TOOLTIP_POSITION} from '../../../common/Tooltip' const MAX_ENTRY = 50 diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddSeverityCell.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddSeverityCell.js index 22342bae62..58500dff16 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddSeverityCell.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/AddSeverityCell.js @@ -2,7 +2,7 @@ import React, {useContext} from 'react' import {Button, BUTTON_SIZE} from '../../../common/Button/Button' import PropTypes from 'prop-types' import IconAdd from '../../../icons/IconAdd' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' export const AddSeverityCell = ({idCategory, severityColumn}) => { const {modifyingCurrentTemplate} = useContext(QualityFrameworkTabContext) diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoriesSeveritiesTable.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoriesSeveritiesTable.js index b5c2116d8a..b401adb98a 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoriesSeveritiesTable.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoriesSeveritiesTable.js @@ -1,5 +1,5 @@ import React, {useContext, useRef} from 'react' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' import {CategoryRow} from './CategoryRow' import {SeveritiyRow} from './SeverityRow' import {SeverityColumn} from './SeverityColumn' @@ -7,18 +7,6 @@ import {AddCategory} from './AddCategory' import {AddSeverity} from './AddSeverity' import {AddSeverityCell} from './AddSeverityCell' -export const getCategoryLabelAndDescription = (category) => { - const [line1, line2] = category.label.split('(') - const label = - line1.slice(-1) === ' ' ? line1.substring(0, line1.length - 1) : line1 - const description = line2 && line2.replace(/[()]/g, '') - - return {label, description} -} -export const formatCategoryDescription = (description) => - `${description[0] !== '(' ? '(' : ''}${description}${description[description.length - 1] !== ')' ? ')' : ''}` -export const getCodeFromLabel = (label) => label.substring(0, 3).toUpperCase() - export const CategoriesSeveritiesTable = () => { const {currentTemplate} = useContext(QualityFrameworkTabContext) diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoriesSeveritiesTableUtils.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoriesSeveritiesTableUtils.js new file mode 100644 index 0000000000..27c1104dff --- /dev/null +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoriesSeveritiesTableUtils.js @@ -0,0 +1,11 @@ +export const getCategoryLabelAndDescription = (category) => { + const [line1, line2] = category.label.split('(') + const label = + line1.slice(-1) === ' ' ? line1.substring(0, line1.length - 1) : line1 + const description = line2 && line2.replace(/[()]/g, '') + + return {label, description} +} +export const formatCategoryDescription = (description) => + `${description[0] !== '(' ? '(' : ''}${description}${description[description.length - 1] !== ')' ? ')' : ''}` +export const getCodeFromLabel = (label) => label.substring(0, 3).toUpperCase() diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoryRow.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoryRow.js index e2ce2419b3..299e3cf844 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoryRow.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoryRow.js @@ -1,6 +1,6 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import PropTypes from 'prop-types' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' import {MenuButton} from '../../../common/MenuButton/MenuButton' import IconDown from '../../../icons/IconDown' import {MenuButtonItem} from '../../../common/MenuButton/MenuButtonItem' @@ -10,7 +10,7 @@ import {SettingsPanelContext} from '../../SettingsPanelContext' import {switchArrayIndex} from '../../../../utils/commonUtils' import LabelWithTooltip from '../../../common/LabelWithTooltip' import {ModifyCategory} from './ModifyCategory' -import {getCategoryLabelAndDescription} from './CategoriesSeveritiesTable' +import {getCategoryLabelAndDescription} from './CategoriesSeveritiesTableUtils' import ChevronDown from '../../../../../img/icons/ChevronDown' export const CategoryRow = ({category, index, shouldScrollIntoView}) => { diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/EptThreshold.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/EptThreshold.js index fcb10cb9d0..cc4351d6c5 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/EptThreshold.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/EptThreshold.js @@ -1,5 +1,5 @@ import React, {useContext, useRef} from 'react' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' export const EptThreshold = () => { const {currentTemplate, templates, modifyingCurrentTemplate} = useContext( diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifyCategory.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifyCategory.js index 4f4069c1ca..d7f2b49877 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifyCategory.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifyCategory.js @@ -9,12 +9,12 @@ import PropTypes from 'prop-types' import Checkmark from '../../../../../img/icons/Checkmark' import {SettingsPanelContext} from '../../SettingsPanelContext' import usePortal from '../../../../hooks/usePortal' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' import { formatCategoryDescription, getCategoryLabelAndDescription, getCodeFromLabel, -} from './CategoriesSeveritiesTable' +} from './CategoriesSeveritiesTableUtils' export const ModifyCategory = ({target, category, setIsEditingName}) => { const {portalTarget} = useContext(SettingsPanelContext) diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifySeverity.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifySeverity.js index 113362e880..066709aa98 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifySeverity.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifySeverity.js @@ -9,8 +9,8 @@ import PropTypes from 'prop-types' import Checkmark from '../../../../../img/icons/Checkmark' import {SettingsPanelContext} from '../../SettingsPanelContext' import usePortal from '../../../../hooks/usePortal' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' -import {getCodeFromLabel} from './CategoriesSeveritiesTable' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' +import {getCodeFromLabel} from './CategoriesSeveritiesTableUtils' export const ModifySeverity = ({ target, diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTab.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTab.js index f62d3e5bca..e3b4f23e5e 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTab.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTab.js @@ -1,4 +1,4 @@ -import React, {useEffect, useRef, useContext, createContext} from 'react' +import React, {useEffect, useRef, useContext} from 'react' import {SubTemplates} from '../SubTemplates' import {SettingsPanelContext} from '../../SettingsPanelContext' import { @@ -69,7 +69,7 @@ const getFilteredSchemaToCompare = (template) => { /* eslint-enable no-unused-vars */ } -export const QualityFrameworkTabContext = createContext({}) +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' export const QualityFrameworkTab = () => { const { diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTab.test.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTab.test.js index 8aa9fd7ef7..271fb8fd79 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTab.test.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTab.test.js @@ -15,7 +15,9 @@ import { } from '@testing-library/react' import useTemplates from '../../../../hooks/useTemplates' import userEvent from '@testing-library/user-event' -import {getCategoryLabelAndDescription} from './CategoriesSeveritiesTable' +import {getCategoryLabelAndDescription} from './CategoriesSeveritiesTableUtils' +// Initializes window.eventHandler (required by Popover component) +import '../../../common/ApplicationWrapper/ApplicationWrapperContext' global.config = { basepath: 'http://localhost/', @@ -79,7 +81,7 @@ test('Render properly and change ept thresholds', async () => { rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() const R1Input = screen.getByTestId('threshold-R1') @@ -122,7 +124,7 @@ test('Change template', async () => { rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() await user.click(screen.getByText('Default')) @@ -186,7 +188,7 @@ test('QF template id not exits and select Standard template', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() expect(screen.getByText('Default')).toBeInTheDocument() @@ -212,7 +214,7 @@ test('Add category', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() const addCategory = screen.getByTestId('qf-add-category') @@ -265,7 +267,7 @@ test('Category rename', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() const categoryRow = within(screen.getByTestId('qf-category-row-2')) @@ -322,7 +324,7 @@ test('Category moveup and movedown', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() let categoryRow = within(screen.getByTestId('qf-category-row-2')) @@ -384,7 +386,7 @@ test('Category delete', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() const categoryRow = within(screen.getByTestId('qf-category-row-2')) @@ -421,7 +423,7 @@ test('Add severity', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() const addSeverity = screen.getByTestId('qf-add-severity') @@ -466,7 +468,7 @@ test('Edit severity', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() const severityCurrentValue = @@ -505,7 +507,7 @@ test('Severity column rename', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() const severityColumn = within(screen.getByTestId('qf-severity-column-1')) @@ -556,7 +558,7 @@ test('Severity column move left and right', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() let severityColumn = within(screen.getByTestId('qf-severity-column-1')) @@ -612,7 +614,7 @@ test('Severity delete', async () => { contextProps.qualityFrameworkTemplates = result.current rerender() } - await waitFor(() => expect(result.current.templates).not.toBe(0)) + await waitFor(() => expect(result.current.templates.length).toBeGreaterThan(0)) refresh() const severityColumn = within(screen.getByTestId('qf-severity-column-1')) diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTabContext.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTabContext.js new file mode 100644 index 0000000000..9c74128e0b --- /dev/null +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/QualityFrameworkTabContext.js @@ -0,0 +1,3 @@ +import {createContext} from 'react' + +export const QualityFrameworkTabContext = createContext({}) diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/SeverityColumn.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/SeverityColumn.js index 998df72066..202c3f9797 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/SeverityColumn.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/SeverityColumn.js @@ -1,6 +1,6 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import PropTypes from 'prop-types' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' import {MenuButton} from '../../../common/MenuButton/MenuButton' import {MenuButtonItem} from '../../../common/MenuButton/MenuButtonItem' import {SettingsPanelContext} from '../../SettingsPanelContext' diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/SeverityRow.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/SeverityRow.js index 562e392b6c..2b3361fcb1 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/SeverityRow.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/SeverityRow.js @@ -1,6 +1,6 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import PropTypes from 'prop-types' -import {QualityFrameworkTabContext} from './QualityFrameworkTab' +import {QualityFrameworkTabContext} from './QualityFrameworkTabContext' import {Button, BUTTON_SIZE} from '../../../common/Button/Button' import IconClose from '../../../icons/IconClose' import Tooltip from '../../../common/Tooltip' diff --git a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplate.js b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplate.js index 0393960a27..bc3712206d 100644 --- a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplate.js +++ b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplate.js @@ -11,14 +11,7 @@ import {flushSync} from 'react-dom' import CatToolActions from '../../../../actions/CatToolActions' import {isEqual} from 'lodash' -export const SUBTEMPLATE_MODIFIERS = { - CREATE: 'create', - UPDATE: 'update', -} - -export const isStandardSubTemplate = ({id} = {}) => id === 0 - -export const SubTemplatesContext = createContext({}) +import {SUBTEMPLATE_MODIFIERS, isStandardSubTemplate, SubTemplatesContext} from './SubTemplateContext' export const SubTemplates = ({ templates, diff --git a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateContext.js b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateContext.js new file mode 100644 index 0000000000..81835abf2d --- /dev/null +++ b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateContext.js @@ -0,0 +1,10 @@ +import {createContext} from 'react' + +export const SUBTEMPLATE_MODIFIERS = { + CREATE: 'create', + UPDATE: 'update', +} + +export const isStandardSubTemplate = ({id} = {}) => id === 0 + +export const SubTemplatesContext = createContext({}) diff --git a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateCreateUpdateControl.js b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateCreateUpdateControl.js index 97f221d4b1..99810b6398 100644 --- a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateCreateUpdateControl.js +++ b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateCreateUpdateControl.js @@ -1,5 +1,5 @@ import React, {useContext} from 'react' -import {SUBTEMPLATE_MODIFIERS, SubTemplatesContext} from './SubTemplate' +import {SUBTEMPLATE_MODIFIERS, SubTemplatesContext} from './SubTemplateContext' import Checkmark from '../../../../../img/icons/Checkmark' import IconClose from '../../../icons/IconClose' import {BUTTON_SIZE, BUTTON_TYPE, Button} from '../../../common/Button/Button' diff --git a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateMoreMenu.js b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateMoreMenu.js index 8fbfa9915e..3a5901abba 100644 --- a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateMoreMenu.js +++ b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateMoreMenu.js @@ -4,7 +4,7 @@ import { SUBTEMPLATE_MODIFIERS, SubTemplatesContext, isStandardSubTemplate, -} from './SubTemplate' +} from './SubTemplateContext' import {MenuButton} from '../../../common/MenuButton/MenuButton' import {MenuButtonItem} from '../../../common/MenuButton/MenuButtonItem' import IconEdit from '../../../icons/IconEdit' diff --git a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateNameInput.js b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateNameInput.js index a585ae6cf2..9ae73c3232 100644 --- a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateNameInput.js +++ b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateNameInput.js @@ -1,5 +1,5 @@ import React, {useContext, useEffect, useRef} from 'react' -import {SUBTEMPLATE_MODIFIERS, SubTemplatesContext} from './SubTemplate' +import {SUBTEMPLATE_MODIFIERS, SubTemplatesContext} from './SubTemplateContext' export const SubTemplateNameInput = () => { const { diff --git a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateSelect.js b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateSelect.js index 1ec886cc8f..b75ecee747 100644 --- a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateSelect.js +++ b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateSelect.js @@ -1,6 +1,6 @@ import React, {useContext, useRef} from 'react' import {Select} from '../../../common/Select' -import {SubTemplatesContext} from './SubTemplate' +import {SubTemplatesContext} from './SubTemplateContext' import HelpCircle from '../../../../../img/icons/HelpCircle' import Tooltip from '../../../common/Tooltip' diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMCreateResourceRow.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMCreateResourceRow.js index 07c04ee2d5..8f20953579 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMCreateResourceRow.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMCreateResourceRow.js @@ -1,10 +1,7 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import PropTypes from 'prop-types' -import { - SPECIAL_ROWS_ID, - TranslationMemoryGlossaryTabContext, - orderTmKeys, -} from './TranslationMemoryGlossaryTab' +import {TranslationMemoryGlossaryTabContext} from './TranslationMemoryGlossaryTabContext' +import {SPECIAL_ROWS_ID, orderTmKeys} from './TranslationMemoryGlossaryTabUtils' import {tmCreateRandUser} from '../../../../api/tmCreateRandUser' import {createNewTmKey} from '../../../../api/createNewTmKey' import {checkTMKey} from '../../../../api/checkTMKey' diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMKeyRow.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMKeyRow.js index e3764955a5..3b06476ea9 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMKeyRow.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMKeyRow.js @@ -1,13 +1,13 @@ import React, {Fragment, useContext, useEffect, useRef, useState} from 'react' import PropTypes from 'prop-types' import {SettingsPanelContext} from '../../SettingsPanelContext' +import {TranslationMemoryGlossaryTabContext} from './TranslationMemoryGlossaryTabContext' import { SPECIAL_ROWS_ID, - TranslationMemoryGlossaryTabContext, getTmDataStructureToSendServer, isOwnerOfKey, orderTmKeys, -} from './TranslationMemoryGlossaryTab' +} from './TranslationMemoryGlossaryTabUtils' import {MenuButton} from '../../../common/MenuButton/MenuButton' import {MenuButtonItem} from '../../../common/MenuButton/MenuButtonItem' import {ImportTMX} from './ImportTMX' diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTab.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTab.js index f9d0c89b28..a686547118 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTab.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTab.js @@ -1,10 +1,4 @@ -import React, { - createContext, - useContext, - useEffect, - useRef, - useState, -} from 'react' +import React, {useContext, useEffect, useRef, useState} from 'react' import {SettingsPanelTable} from '../../SettingsPanelTable/SettingsPanelTable' import {SettingsPanelContext} from '../../SettingsPanelContext' import {ApplicationWrapperContext} from '../../../common/ApplicationWrapper/ApplicationWrapperContext' @@ -111,7 +105,7 @@ export const getTmDataStructureToSendServer = ({tmKeys = [], keysOrdered}) => { }) } -export const TranslationMemoryGlossaryTabContext = createContext({}) +import {TranslationMemoryGlossaryTabContext} from './TranslationMemoryGlossaryTabContext' export const TranslationMemoryGlossaryTab = () => { const {tmKeys, setTmKeys, modifyingCurrentTemplate, currentProjectTemplate} = diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTabContext.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTabContext.js new file mode 100644 index 0000000000..01ff6ba8b4 --- /dev/null +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTabContext.js @@ -0,0 +1,3 @@ +import {createContext} from 'react' + +export const TranslationMemoryGlossaryTabContext = createContext({}) diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTabUtils.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTabUtils.js new file mode 100644 index 0000000000..41bc6fcddb --- /dev/null +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTabUtils.js @@ -0,0 +1,46 @@ +export const SPECIAL_ROWS_ID = { + defaultTranslationMemory: 'mmSharedKey', + addSharedResource: 'addSharedResource', + newResource: 'newResource', +} + +export const isOwnerOfKey = (key) => !/[*]/g.test(key) + +export const orderTmKeys = (tmKeys, keysOrdered) => { + const order = (acc, cur) => { + const copyAcc = [...acc] + const index = keysOrdered.findIndex((key) => key === cur.key) + + if (index >= 0) { + const previousItem = copyAcc[index] + copyAcc[index] = cur + if (previousItem) copyAcc.push(previousItem) + } else { + copyAcc.push(cur) + } + return copyAcc + } + return Array.isArray(keysOrdered) + ? tmKeys.reduce(order, []).filter((row) => row) + : tmKeys +} + +export const getTmDataStructureToSendServer = ({tmKeys = [], keysOrdered}) => { + const mine = tmKeys + .filter(({key, isActive}) => isOwnerOfKey(key) && isActive) + .map(({tm, glos, key, name, r, w, penalty}) => ({ + tm, + glos, + key, + name, + r, + w, + penalty, + })) + + return JSON.stringify({ + ownergroup: [], + mine: orderTmKeys(mine, keysOrdered), + anonymous: [], + }) +} diff --git a/public/js/components/settingsPanel/ProjectTemplate/CreateUpdateControl.js b/public/js/components/settingsPanel/ProjectTemplate/CreateUpdateControl.js index d53226d543..f2cbbd759d 100644 --- a/public/js/components/settingsPanel/ProjectTemplate/CreateUpdateControl.js +++ b/public/js/components/settingsPanel/ProjectTemplate/CreateUpdateControl.js @@ -1,6 +1,6 @@ import React, {useContext} from 'react' import {ProjectTemplateContext} from './ProjectTemplateContext' -import {TEMPLATE_MODIFIERS} from './ProjectTemplate' +import {TEMPLATE_MODIFIERS} from './ProjectTemplateConstants' import IconClose from '../../icons/IconClose' import Checkmark from '../../../../img/icons/Checkmark' import {BUTTON_SIZE, BUTTON_TYPE, Button} from '../../common/Button/Button' diff --git a/public/js/components/settingsPanel/ProjectTemplate/MoreMenu.js b/public/js/components/settingsPanel/ProjectTemplate/MoreMenu.js index 5d77e5408b..da7564eb79 100644 --- a/public/js/components/settingsPanel/ProjectTemplate/MoreMenu.js +++ b/public/js/components/settingsPanel/ProjectTemplate/MoreMenu.js @@ -6,7 +6,7 @@ import {MenuButtonItem} from '../../common/MenuButton/MenuButtonItem' import {ProjectTemplateContext} from './ProjectTemplateContext' import {deleteProjectTemplate} from '../../../api/deleteProjectTemplate' import {isStandardTemplate} from '../../../hooks/useProjectTemplates' -import {TEMPLATE_MODIFIERS} from './ProjectTemplate' +import {TEMPLATE_MODIFIERS} from './ProjectTemplateConstants' import {SettingsPanelContext} from '../SettingsPanelContext' import IconEdit from '../../icons/IconEdit' import Trash from '../../../../img/icons/Trash' diff --git a/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplate.js b/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplate.js index 31a1ce8e6e..bcdac4c2e5 100644 --- a/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplate.js +++ b/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplate.js @@ -22,10 +22,7 @@ import {isEqual} from 'lodash' import ModalsActions from '../../../actions/ModalsActions' import {ConfirmDeleteResourceProjectTemplates} from '../../modals/ConfirmDeleteResourceProjectTemplates' -export const TEMPLATE_MODIFIERS = { - CREATE: 'create', - UPDATE: 'update', -} +import {TEMPLATE_MODIFIERS} from './ProjectTemplateConstants' export const ProjectTemplate = ({portalTarget}) => { const { diff --git a/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplateConstants.js b/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplateConstants.js new file mode 100644 index 0000000000..1e97bcc460 --- /dev/null +++ b/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplateConstants.js @@ -0,0 +1,4 @@ +export const TEMPLATE_MODIFIERS = { + CREATE: 'create', + UPDATE: 'update', +} diff --git a/public/js/components/settingsPanel/ProjectTemplate/TemplateNameInput.js b/public/js/components/settingsPanel/ProjectTemplate/TemplateNameInput.js index 8a54610f79..b1c1922e19 100644 --- a/public/js/components/settingsPanel/ProjectTemplate/TemplateNameInput.js +++ b/public/js/components/settingsPanel/ProjectTemplate/TemplateNameInput.js @@ -1,6 +1,6 @@ import React, {useContext, useEffect, useRef} from 'react' import {ProjectTemplateContext} from './ProjectTemplateContext' -import {TEMPLATE_MODIFIERS} from './ProjectTemplate' +import {TEMPLATE_MODIFIERS} from './ProjectTemplateConstants' export const TemplateNameInput = () => { const { diff --git a/public/js/components/settingsPanel/SettingsPanel.js b/public/js/components/settingsPanel/SettingsPanel.js index bd265c1b1c..42817f3f65 100644 --- a/public/js/components/settingsPanel/SettingsPanel.js +++ b/public/js/components/settingsPanel/SettingsPanel.js @@ -137,20 +137,7 @@ const DEFAULT_CONTENTS = (isCattool = config.is_cattool) => { ] } -export const DEFAULT_ENGINE_MEMORY = { - id: 1, - name: 'ModernMT Lite', - description: ( -
click here.', - }} - /> - ), - default: true, - engine_type: 'MMTLite', -} + export const SettingsPanel = ({ onClose, diff --git a/public/js/components/settingsPanel/SettingsPanelConstants.js b/public/js/components/settingsPanel/SettingsPanelConstants.js new file mode 100644 index 0000000000..9558b93948 --- /dev/null +++ b/public/js/components/settingsPanel/SettingsPanelConstants.js @@ -0,0 +1,55 @@ +import React from 'react' +import {SCHEMA_KEYS} from '../../hooks/useProjectTemplates' + +export const SETTINGS_PANEL_TABS = { + translationMemoryGlossary: 'tm', + machineTranslation: 'mt', + other: 'other', + analysis: 'analysis', + qualityFramework: 'qf', + fileImport: 'fileImport', + editorSettings: 'editorSettings', + editorOther: 'editorOther', +} + +export const TEMPLATE_PROPS_BY_TAB = { + [SETTINGS_PANEL_TABS.translationMemoryGlossary]: [ + SCHEMA_KEYS.tm, + SCHEMA_KEYS.getPublicMatches, + SCHEMA_KEYS.publicTmPenalty, + SCHEMA_KEYS.pretranslate100, + SCHEMA_KEYS.tmPrioritization, + ], + [SETTINGS_PANEL_TABS.machineTranslation]: [SCHEMA_KEYS.mt], + [SETTINGS_PANEL_TABS.qualityFramework]: [SCHEMA_KEYS.qaModelTemplateId], + [SETTINGS_PANEL_TABS.fileImport]: [ + SCHEMA_KEYS.segmentationRule, + SCHEMA_KEYS.filtersTemplateId, + SCHEMA_KEYS.XliffConfigTemplateId, + ], + [SETTINGS_PANEL_TABS.analysis]: [SCHEMA_KEYS.payableRateTemplateId], + [SETTINGS_PANEL_TABS.other]: [ + SCHEMA_KEYS.speech2text, + SCHEMA_KEYS.tagProjection, + SCHEMA_KEYS.lexica, + SCHEMA_KEYS.crossLanguageMatches, + SCHEMA_KEYS.idTeam, + ], + [SETTINGS_PANEL_TABS.editorSettings]: [], + [SETTINGS_PANEL_TABS.editorOther]: [], +} + +export const DEFAULT_ENGINE_MEMORY = { + id: 1, + name: 'ModernMT Lite', + description: ( +
click here.', + }} + /> + ), + default: true, + engine_type: 'MMTLite', +} diff --git a/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelRow.js b/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelRow.js index 0c38614932..83752816cd 100644 --- a/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelRow.js +++ b/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelRow.js @@ -1,6 +1,6 @@ import React, {useRef, useState, forwardRef, useContext} from 'react' import PropTypes from 'prop-types' -import {SettingsPanelTableContext} from './SettingsPanelTable' +import {SettingsPanelTableContext} from './SettingsPanelTableContext' const ROW_HEIGHT = 50 diff --git a/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelTable.js b/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelTable.js index c13340b449..b77380d320 100644 --- a/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelTable.js +++ b/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelTable.js @@ -1,17 +1,10 @@ -import React, { - useCallback, - useRef, - createRef, - useState, - createContext, - Fragment, -} from 'react' +import React, {useCallback, useRef, createRef, useState, Fragment} from 'react' import PropTypes from 'prop-types' import {SettingsPanelRow} from './SettingsPanelRow' -import {SPECIAL_ROWS_ID} from '../Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTab' +import {SPECIAL_ROWS_ID} from '../Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTabUtils' import {TmPrioritization} from '../Contents/TranslationMemoryGlossaryTab/TmPrioritization' -export const SettingsPanelTableContext = createContext({}) +import {SettingsPanelTableContext} from './SettingsPanelTableContext' export const SettingsPanelTable = ({ columns, diff --git a/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelTableContext.js b/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelTableContext.js new file mode 100644 index 0000000000..3ed9eb1cbc --- /dev/null +++ b/public/js/components/settingsPanel/SettingsPanelTable/SettingsPanelTableContext.js @@ -0,0 +1,3 @@ +import {createContext} from 'react' + +export const SettingsPanelTableContext = createContext({}) diff --git a/public/js/components/settingsPanel/Tab.js b/public/js/components/settingsPanel/Tab.js index 699481450f..93c666cd7d 100644 --- a/public/js/components/settingsPanel/Tab.js +++ b/public/js/components/settingsPanel/Tab.js @@ -1,7 +1,7 @@ import React, {useContext} from 'react' import PropTypes from 'prop-types' import {SettingsPanelContext} from './SettingsPanelContext' -import {TEMPLATE_PROPS_BY_TAB} from './SettingsPanel' +import {TEMPLATE_PROPS_BY_TAB} from './SettingsPanelConstants' export const Tab = ({id, label}) => { const { diff --git a/public/js/components/xliffToTarget/UploadXliff.js b/public/js/components/xliffToTarget/UploadXliff.js index bb63758254..74d3270c2e 100644 --- a/public/js/components/xliffToTarget/UploadXliff.js +++ b/public/js/components/xliffToTarget/UploadXliff.js @@ -1,13 +1,12 @@ import React, {useCallback, useState} from 'react' import {Button, BUTTON_SIZE, BUTTON_TYPE} from '../common/Button/Button' -import {DeleteIcon} from '../segments/SegmentFooterTabGlossary' +import {DeleteIcon} from '../segments/SegmentFooterTabGlossary/GlossaryConstants' import FileUploadIconBig from '../../../img/icons/FileUploadIconBig' import CommonUtils from '../../utils/commonUtils' -import IconAdd from '../icons/IconAdd' import IconClose from '../icons/IconClose' import {PROGRESS_BAR_SIZE, ProgressBar} from '../common/ProgressBar' import {xliffToTargetUpload} from '../../api/xliffToTargetUpload' -import {getPrintableFileSize} from '../createProject/UploadFile' +import {getPrintableFileSize} from '../createProject/UploadFileUtils' import {saveAs} from 'file-saver' const b64toBlob = (b64Data, contentType, sliceSize) => { diff --git a/public/js/constants/ModalKeys.js b/public/js/constants/ModalKeys.js new file mode 100644 index 0000000000..76ca8449fc --- /dev/null +++ b/public/js/constants/ModalKeys.js @@ -0,0 +1,16 @@ +export const MODAL_KEY = { + CONFIRM_MESSAGE: 'ConfirmMessage', + SPLIT_JOB: 'SplitJob', + CREATE_TEAM: 'CreateTeam', + MODIFY_TEAM: 'ModifyTeam', + PREFERENCES: 'Preferences', + SUCCESS: 'Success', + ONBOARDING: 'OnBoarding', + DOWNLOAD_ALERT: 'DownloadAlert', + ALERT: 'Alert', + REVISION_FEEDBACK: 'RevisionFeedback', + COPY_SOURCE: 'CopySource', + UNLOCK_ALL_SEGMENTS: 'UnlockAllSegments', +} + +export const COPY_SOURCE_COOKIE = 'source_copied_to_target' diff --git a/public/js/constants/OnBoardingConstants.js b/public/js/constants/OnBoardingConstants.js new file mode 100644 index 0000000000..d9ffa2db07 --- /dev/null +++ b/public/js/constants/OnBoardingConstants.js @@ -0,0 +1,7 @@ +export const ONBOARDING_STEP = { + LOGIN: 'login', + REGISTER: 'register', + PASSWORD_RESET: 'passwordReset', + FORGOT_PASSWORD: 'forgotPassword', + SET_NEW_PASSWORD: 'setNewPassword', +} diff --git a/public/js/constants/SegmentTabConstants.js b/public/js/constants/SegmentTabConstants.js new file mode 100644 index 0000000000..cf77ce9198 --- /dev/null +++ b/public/js/constants/SegmentTabConstants.js @@ -0,0 +1,13 @@ +export const TAB = { + MATCHES: 'matches', + CONCORDANCES: 'concordances', + GLOSSARY: 'glossary', + ALTERNATIVES: 'alternatives', + MESSAGES: 'messages', + MULTIMATCHES: 'multiMatches', + AI_ASSISTANT: 'AiAssistant', + LARA_STYLES: 'laraStyles', + AI_ALTERNATIVES: 'aiAlternatives', + AI_FEEDBACK: 'aiFeedback', + ICU: 'icu', +} diff --git a/public/js/hooks/useSocketLayer.js b/public/js/hooks/useSocketLayer.js index ba5d441d1e..48c9ddec67 100644 --- a/public/js/hooks/useSocketLayer.js +++ b/public/js/hooks/useSocketLayer.js @@ -1,7 +1,6 @@ import {useCallback, useEffect, useRef, useState} from 'react' import {getSocketAuthToken} from '../api/loginUser' - -const {io} = require('socket.io-client') +import {io} from 'socket.io-client' // Object to represent connection states export const ConnectionStates = { diff --git a/public/js/pages/ActivityLog.js b/public/js/pages/ActivityLog.js index 6fc41a0068..73e63c917d 100644 --- a/public/js/pages/ActivityLog.js +++ b/public/js/pages/ActivityLog.js @@ -1,5 +1,4 @@ import React, { - createContext, useContext, useEffect, useRef, @@ -11,10 +10,9 @@ import {ApplicationWrapperContext} from '../components/common/ApplicationWrapper import Footer from '../components/footer/Footer' import SocketListener from '../sse/SocketListener' import {mountPage} from './mountPage' -import { - ACTIVITY_LOG_COLUMNS, - ActivityLogTable, -} from '../components/activityLog/ActivityLogTable' +import {ActivityLogTable} from '../components/activityLog/ActivityLogTable' +import {ACTIVITY_LOG_COLUMNS} from '../components/activityLog/ActivityLogConstants' +import {ActivityLogContext} from '../components/activityLog/ActivityLogContext' import {getActivityLog} from '../api/getActivityLog/getActivityLog' import {getProject} from '../api/getProject/getProject' import {FilterColumn} from '../components/activityLog/FilterColumn' @@ -24,7 +22,7 @@ const headerMountPoint = document.querySelector('header.upload-page-header') const projectId = config.project_id const password = config.password -export const ActivityLogContext = createContext({}) + export const ActivityLog = () => { const {isUserLogged, userInfo} = useContext(ApplicationWrapperContext) diff --git a/public/js/pages/CatTool.js b/public/js/pages/CatTool.js index f1c0c32aac..da116edf5d 100644 --- a/public/js/pages/CatTool.js +++ b/public/js/pages/CatTool.js @@ -21,10 +21,10 @@ import LXQ from '../utils/lxq.main' import {getTmKeysUser} from '../api/getTmKeysUser' import {getMTEngines as getMtEnginesApi} from '../api/getMTEngines' import { - DEFAULT_ENGINE_MEMORY, SETTINGS_PANEL_TABS, SettingsPanel, } from '../components/settingsPanel' +import {DEFAULT_ENGINE_MEMORY} from '../components/settingsPanel/SettingsPanelConstants' import {getTmKeysJob} from '../api/getTmKeysJob' import {getSupportedLanguages} from '../api/getSupportedLanguages' import ApplicationStore from '../stores/ApplicationStore' diff --git a/public/js/pages/NewProject.js b/public/js/pages/NewProject.js index 8d37e30751..16634a4d06 100644 --- a/public/js/pages/NewProject.js +++ b/public/js/pages/NewProject.js @@ -27,7 +27,8 @@ import {TargetLanguagesSelect} from '../components/createProject/TargetLanguages import {TmGlossarySelect} from '../components/createProject/TmGlossarySelect' import {SourceLanguageSelect} from '../components/createProject/SourceLanguageSelect' import CommonUtils from '../utils/commonUtils' -import {DEFAULT_ENGINE_MEMORY, SettingsPanel} from '../components/settingsPanel' +import {SettingsPanel} from '../components/settingsPanel' +import {DEFAULT_ENGINE_MEMORY} from '../components/settingsPanel/SettingsPanelConstants' import {getMTEngines as getMtEnginesApi} from '../api/getMTEngines' import {tmCreateRandUser} from '../api/tmCreateRandUser' import {getSupportedFiles} from '../api/getSupportedFiles' diff --git a/public/js/stores/SegmentStore.js b/public/js/stores/SegmentStore.js index bf9b884915..290d96b484 100644 --- a/public/js/stores/SegmentStore.js +++ b/public/js/stores/SegmentStore.js @@ -37,9 +37,7 @@ import $ from 'jquery' import AppDispatcher from './AppDispatcher' import SegmentConstants from '../constants/SegmentConstants' -import SegmentUtils from '../utils/segmentUtils' import EditAreaConstants from '../constants/EditAreaConstants' -import DraftMatecatUtils from '../components/segments/utils/DraftMatecatUtils' import { JOB_WORD_CONT_TYPE, REVISE_STEP_NUMBER, @@ -47,6 +45,13 @@ import { splittedTranslationPlaceholder, } from '../constants/Constants' +import {transformTagsToText, removeTagsFromText, checkXliffTagsInText} from '../components/segments/utils/DraftMatecatUtils/tagUtils' +import {checkTPEnabled, checkCurrentSegmentTPEnabled} from '../utils/tagProjectionUtils' +// Lazy-loaded to break circular dependencies +let _SegmentUtils +const getSegmentUtils = () => + _SegmentUtils || (_SegmentUtils = require('../utils/segmentUtils').default) + EventEmitter.prototype.setMaxListeners(0) const normalizeSetUpdateGlossary = (term) => { @@ -166,7 +171,7 @@ const SegmentStore = assign({}, EventEmitter.prototype, { parsed_time_to_edit: ['00', '00', '00', '00'], readonly: false, segment: splittedSourceAr[i], - decodedSource: DraftMatecatUtils.transformTagsToText( + decodedSource: transformTagsToText( segment.segment, ), segment_hash: segment.segment_hash, @@ -184,7 +189,7 @@ const SegmentStore = assign({}, EventEmitter.prototype, { originalDecodedTranslation: translation ? translation : '', translation: translation ? translation : '', decodedTranslation: - DraftMatecatUtils.transformTagsToText(translation), + transformTagsToText(translation), warning: false, warnings: {}, tagged: !this.hasSegmentTagProjectionEnabled(segment), @@ -219,7 +224,7 @@ const SegmentStore = assign({}, EventEmitter.prototype, { : segment.status segment.splitted = false segment.original_translation = segment.translation - segment.unlocked = SegmentUtils.isUnlockedSegment(segment) + segment.unlocked = getSegmentUtils().isUnlockedSegment(segment) segment.warnings = {} segment.tagged = !this.hasSegmentTagProjectionEnabled(segment) segment.edit_area_locked = false @@ -233,16 +238,16 @@ const SegmentStore = assign({}, EventEmitter.prototype, { segment.occurrencesInSearch = occurrencesInSearch segment.searchParams = this.searchParams segment.originalDecodedTranslation = segment.translation - segment.decodedTranslation = DraftMatecatUtils.transformTagsToText( + segment.decodedTranslation = transformTagsToText( segment.translation, ) - segment.decodedSource = DraftMatecatUtils.transformTagsToText( + segment.decodedSource = transformTagsToText( segment.segment, ) - segment.updatedSource = SegmentUtils.checkCurrentSegmentTPEnabled( + segment.updatedSource = checkCurrentSegmentTPEnabled( segment, ) - ? DraftMatecatUtils.removeTagsFromText(segment.segment) + ? removeTagsFromText(segment.segment) : segment.segment segment.openComments = false segment.openSplit = false @@ -356,7 +361,7 @@ const SegmentStore = assign({}, EventEmitter.prototype, { updateOriginalTranslation(sid, translation) { const index = this.getSegmentIndex(sid) if (index === -1) return - const newTrans = DraftMatecatUtils.transformTagsToText(translation) + const newTrans = transformTagsToText(translation) this._segments = this._segments.setIn( [index, 'originalDecodedTranslation'], @@ -994,11 +999,11 @@ const SegmentStore = assign({}, EventEmitter.prototype, { ) }, hasSegmentTagProjectionEnabled: function (segment) { - if (SegmentUtils.checkTPEnabled()) { + if (checkTPEnabled()) { if ( (segment.status === 'NEW' || segment.status === 'DRAFT') && - DraftMatecatUtils.checkXliffTagsInText(segment.segment) && - !DraftMatecatUtils.checkXliffTagsInText(segment.translation) + checkXliffTagsInText(segment.segment) && + !checkXliffTagsInText(segment.translation) ) { return true } diff --git a/public/js/utils/commonUtils.js b/public/js/utils/commonUtils.js index 645d00e1d6..20073c224f 100644 --- a/public/js/utils/commonUtils.js +++ b/public/js/utils/commonUtils.js @@ -1,11 +1,22 @@ import Cookies from 'js-cookie' import $ from 'jquery' -import OfflineUtils from './offlineUtils' -import SegmentActions from '../actions/SegmentActions' -import SegmentStore from '../stores/SegmentStore' import AlertModal from '../components/modals/AlertModal' import ModalsActions from '../actions/ModalsActions' -import {isTranslationTailEmpty} from '../setTranslationUtil' +import SegmentStore from '../stores/SegmentStore' +import { + getLastSegmentFromLocalStorage, + setLastSegmentFromLocalStorage, +} from './segmentLocalStorage' + +import OfflineUtils from './offlineUtils' + +// Lazy-loaded to break circular dependencies +let _SegmentActions +const getSegmentActions = () => + _SegmentActions || + (_SegmentActions = require('../actions/SegmentActions').default) +const checkTranslationTailEmpty = () => + require('../setTranslationUtil').isTranslationTailEmpty() const CommonUtils = { millisecondsToTime(milli) { @@ -122,7 +133,7 @@ const CommonUtils = { var currentSegment = SegmentStore.getCurrentSegment() if (segment && currentSegment?.sid === segment.sid) return if (segment && !segment.opened) { - SegmentActions.openSegment(this.parsedHash.segmentId, true) + getSegmentActions().openSegment(this.parsedHash.segmentId, true) } } @@ -169,7 +180,7 @@ const CommonUtils = { } if (OfflineUtils.offline) { - if (!isTranslationTailEmpty()) { + if (!checkTranslationTailEmpty()) { return say_goodbye( 'You are working in offline mode. If you proceed to refresh you will lose all the pending translations. ' + 'Do you want to proceed with the refresh ?', @@ -277,21 +288,8 @@ const CommonUtils = { navigator.userAgent.search('Safari') >= 0 && navigator.userAgent.search('Chrome') < 0 && !CommonUtils.isLocalStorageNameSupported(), - getLastSegmentFromLocalStorage: function () { - let localStorageCurrentSegmentId = - 'currentSegmentId-' + config.id_job + config.password - return localStorage.getItem(localStorageCurrentSegmentId) - }, - setLastSegmentFromLocalStorage: function (segmentId) { - let localStorageCurrentSegmentId = - 'currentSegmentId-' + config.id_job + config.password - try { - localStorage.setItem(localStorageCurrentSegmentId, segmentId) - } catch (e) { - this.clearStorage('currentSegmentId') - localStorage.setItem(localStorageCurrentSegmentId, segmentId) - } - }, + getLastSegmentFromLocalStorage, + setLastSegmentFromLocalStorage, clearStorage: function (what) { $.each(localStorage, function (k) { if (k.substring(0, what.length) === what) { diff --git a/public/js/utils/lxq.main.js b/public/js/utils/lxq.main.js index 0a4dc1c00f..efd0859dad 100644 --- a/public/js/utils/lxq.main.js +++ b/public/js/utils/lxq.main.js @@ -4,7 +4,11 @@ import {merge} from 'lodash/object' import {isUndefined} from 'lodash' import $ from 'jquery' -import SegmentActions from '../actions/SegmentActions' +import { + qaComponentsetLxqIssues, + addLexiqaHighlight, +} from '../actions/segmentDispatchActions' +import {getSegmentsQa} from '../actions/segmentQaActions' import {toggleTagLexica} from '../api/toggleTagLexica' import {getLexiqaWarnings as getLexiqaWarningsApi} from '../api/getLexiqaWarnings' import {lexiqaIgnoreError} from '../api/lexiqaIgnoreError' @@ -149,14 +153,14 @@ const LXQ = { if (!LXQ.initialized) { LXQ.init() } else { - SegmentActions.qaComponentsetLxqIssues(LXQ.lexiqaData.segments) + qaComponentsetLxqIssues(LXQ.lexiqaData.segments) } - SegmentActions.getSegmentsQa(SegmentStore.getCurrentSegment()) + getSegmentsQa(SegmentStore.getCurrentSegment()) }) }, disable: function () { toggleTagLexica({enabled: false}).then(() => { - SegmentActions.qaComponentsetLxqIssues([]) + qaComponentsetLxqIssues([]) }) }, checkCanActivate: function () { @@ -264,7 +268,7 @@ const LXQ = { LXQ.lexiqaData.segments.push(id_segment) LXQ.updateWarningsUI() } - SegmentActions.addLexiqaHighlight(id_segment, highlights) + addLexiqaHighlight(id_segment, highlights) if (!(LXQ.getVisibleWarningsCountForSegment(id_segment) > 0)) { noVisibleErrorsFound = true @@ -284,7 +288,7 @@ const LXQ = { }) }, lxqRemoveSegmentFromWarningList: function (id_segment) { - SegmentActions.addLexiqaHighlight(id_segment, {}) + addLexiqaHighlight(id_segment, {}) LXQ.removeSegmentWarning(id_segment) }, getLexiqaWarnings: function (callback) { @@ -345,7 +349,7 @@ const LXQ = { if (!LXQ.getVisibleWarningsCountForSegment(element.segid) > 0) { LXQ.removeSegmentWarning(element.segid) } - SegmentActions.addLexiqaHighlight(element.segid, highlights) + addLexiqaHighlight(element.segid, highlights) }) LXQ.updateWarningsUI() @@ -364,7 +368,7 @@ const LXQ = { const segments = LXQ.lexiqaData.segments.filter(function (id_segment) { return Object.hasOwn(LXQ.lexiqaData.lexiqaWarnings, id_segment) }) - SegmentActions.qaComponentsetLxqIssues(segments) + qaComponentsetLxqIssues(segments) }, removeSegmentWarning: function (idSegment) { let ind = LXQ.lexiqaData.segments.indexOf(idSegment) @@ -677,7 +681,7 @@ const LXQ = { highlights.target[qadata.category].push(qadata) } }) - SegmentActions.addLexiqaHighlight(segmentId, highlights) + addLexiqaHighlight(segmentId, highlights) }, postIgnoreError: function (errorid) { lexiqaIgnoreError({errorId: errorid}) diff --git a/public/js/utils/offlineUtils.js b/public/js/utils/offlineUtils.js index c5392f2ece..418541aceb 100644 --- a/public/js/utils/offlineUtils.js +++ b/public/js/utils/offlineUtils.js @@ -1,8 +1,21 @@ -import SegmentActions from '../actions/SegmentActions' +import { + addClassToSegment, + removeClassToSegment, +} from '../actions/segmentClassActions' import {checkConnectionPing} from '../api/checkConnectionPing' -import CatToolActions from '../actions/CatToolActions' +import { + addNotification, + removeAllNotifications, +} from '../actions/notificationActions' import SegmentStore from '../stores/SegmentStore' -import {execSetTranslationTail} from '../setTranslationUtil' + +// Lazy-loaded to break circular dependency with setTranslationUtil +// Using require() instead of import so madge's ES6 detective doesn't +// register this as a static edge. Do NOT convert back to import. +let _SetTranslationUtil +const getSetTranslationUtil = () => + _SetTranslationUtil || + (_SetTranslationUtil = require('../setTranslationUtil')) const OfflineUtils = { offline: false, @@ -26,7 +39,7 @@ const OfflineUtils = { allowHtml: true, timer: 7000, } - CatToolActions.addNotification(notification) + addNotification(notification) }) .catch(() => { this.offline = true @@ -49,10 +62,10 @@ const OfflineUtils = { autoDismiss: true, timer: 10000, openCallback: () => { - CatToolActions.removeAllNotifications() + removeAllNotifications() }, } - CatToolActions.addNotification(notification) + addNotification(notification) clearInterval(this.currentConnectionCountdown) clearInterval(this.checkingConnection) @@ -67,7 +80,7 @@ const OfflineUtils = { checkConnectionPing() .then(() => { this.endOfflineMode() - execSetTranslationTail() + getSetTranslationUtil().execSetTranslationTail() //reset counter this.offlineCacheRemaining = this.offlineCacheSize }) @@ -97,7 +110,7 @@ const OfflineUtils = { allowHtml: true, timer: 7000, } - CatToolActions.addNotification(notification) + addNotification(notification) } }, incrementOfflineCacheRemaining: function () { @@ -107,13 +120,13 @@ const OfflineUtils = { changeStatusOffline: function (sid) { if (SegmentStore.getSegmentById(sid)) { - SegmentActions.removeClassToSegment(sid, 'status-draft') - SegmentActions.removeClassToSegment(sid, 'status-approved') - SegmentActions.removeClassToSegment(sid, 'status-new') - SegmentActions.removeClassToSegment(sid, 'status-rejected') - SegmentActions.removeClassToSegment(sid, 'status-fixed') - SegmentActions.removeClassToSegment(sid, 'status-rebutted') - SegmentActions.addClassToSegment(sid, 'status-translated') + removeClassToSegment(sid, 'status-draft') + removeClassToSegment(sid, 'status-approved') + removeClassToSegment(sid, 'status-new') + removeClassToSegment(sid, 'status-rejected') + removeClassToSegment(sid, 'status-fixed') + removeClassToSegment(sid, 'status-rebutted') + addClassToSegment(sid, 'status-translated') } }, } diff --git a/public/js/utils/segmentLocalStorage.js b/public/js/utils/segmentLocalStorage.js new file mode 100644 index 0000000000..ada89c5ea2 --- /dev/null +++ b/public/js/utils/segmentLocalStorage.js @@ -0,0 +1,23 @@ +const clearStorage = (prefix) => { + const keys = Object.keys(localStorage) + for (let i = 0; i < keys.length; i++) { + if (keys[i].substring(0, prefix.length) === prefix) { + localStorage.removeItem(keys[i]) + } + } +} + +export const getLastSegmentFromLocalStorage = () => { + const key = 'currentSegmentId-' + config.id_job + config.password + return localStorage.getItem(key) +} + +export const setLastSegmentFromLocalStorage = (segmentId) => { + const key = 'currentSegmentId-' + config.id_job + config.password + try { + localStorage.setItem(key, segmentId) + } catch (e) { + clearStorage('currentSegmentId') + localStorage.setItem(key, segmentId) + } +} diff --git a/public/js/utils/speech2text.js b/public/js/utils/speech2text.js index d3a74f62fb..6c558de864 100644 --- a/public/js/utils/speech2text.js +++ b/public/js/utils/speech2text.js @@ -1,4 +1,8 @@ -import SegmentActions from '../actions/SegmentActions' +import { + replaceEditAreaTextContent, + modifiedTranslation, + activateTab, +} from '../actions/segmentDispatchActions' import SegmentStore from '../stores/SegmentStore' import CatToolActions from '../actions/CatToolActions' import $ from 'jquery' @@ -99,7 +103,7 @@ const Speech2Text = { if (Speech2Text.shouldEmptyTargetElement(segment)) { Speech2Text.finalTranscript = '' - SegmentActions.replaceEditAreaTextContent(Speech2Text.sid, '') + replaceEditAreaTextContent(Speech2Text.sid, '') } else { Speech2Text.finalTranscript = segment.translation + ' ' } @@ -160,8 +164,8 @@ const Speech2Text = { Speech2Text.linebreak(Speech2Text.finalTranscript) + Speech2Text.linebreak(Speech2Text.interimTranscript) let sid = Speech2Text.sid - SegmentActions.replaceEditAreaTextContent(sid, html) - SegmentActions.modifiedTranslation(sid, true) + replaceEditAreaTextContent(sid, html) + modifiedTranslation(sid, true) } }, linebreak: function (s) { @@ -187,7 +191,7 @@ const Speech2Text = { Speech2Text.isToKeepRecognizing = false }, showMatches: function () { - SegmentActions.activateTab(SegmentStore.getCurrentSegmentId(), 'matches') + activateTab(SegmentStore.getCurrentSegmentId(), 'matches') }, animateSpeechActive: function () { Speech2Text.microphone.removeClass('micSpeechReceiving') diff --git a/public/js/utils/tagProjectionUtils.js b/public/js/utils/tagProjectionUtils.js new file mode 100644 index 0000000000..18c5e6b35b --- /dev/null +++ b/public/js/utils/tagProjectionUtils.js @@ -0,0 +1,32 @@ +import UserStore from '../stores/UserStore' +import { + removeTagsFromText, + hasDataOriginalTags, +} from '../components/segments/utils/DraftMatecatUtils/tagUtils' + +export const checkTPSupportedLanguage = () => { + const languagesKey = `${config.source_code.split('-')[0]}-${config.target_code.split('-')[0]}` + const languagesKeyRev = `${config.target_code.split('-')[0]}-${config.source_code.split('-')[0]}` + return Object.keys(config.tag_projection_languages).some( + (key) => key === languagesKey || key === languagesKeyRev, + ) +} + +export const checkTPEnabled = () => { + return ( + checkTPSupportedLanguage() && + UserStore.getUserMetadata()?.guess_tags === 1 && + !!!config.isReview + ) +} + +export const checkCurrentSegmentTPEnabled = (segment) => { + if (!segment) return false + if (!checkTPEnabled()) return false + const segmentNoTags = removeTagsFromText(segment.segment) + const tagProjectionEnabled = + hasDataOriginalTags(segment.segment) && + !segment.tagged && + segmentNoTags !== '' + return tagProjectionEnabled && !segment.tagged +} diff --git a/public/js/utils/textUtils.js b/public/js/utils/textUtils.js index c60456c1cd..d7f6b86a2b 100644 --- a/public/js/utils/textUtils.js +++ b/public/js/utils/textUtils.js @@ -1,6 +1,6 @@ import {isUndefined} from 'lodash' import $ from 'jquery' -import {regexWordDelimiter} from '../components/segments/utils/DraftMatecatUtils/textUtils' +import {regexWordDelimiter} from '../components/segments/utils/DraftMatecatUtils/textConstants' import CommonUtils from './commonUtils' import diff_match_patch from 'diff-match-patch' import {tagSignatures} from '../components/segments/utils/DraftMatecatUtils/tagModel' diff --git a/yarn.lock b/yarn.lock index d896f1f0b4..254319bdca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -267,6 +267,13 @@ dependencies: "@babel/types" "^7.28.4" +"@babel/parser@^7.26.7", "@babel/parser@^7.28.6", "@babel/parser@^7.29.0", "@babel/parser@^7.29.2": + version "7.29.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.2.tgz#58bd50b9a7951d134988a1ae177a35ef9a703ba1" + integrity sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA== + dependencies: + "@babel/types" "^7.29.0" + "@babel/parser@^7.28.3": version "7.28.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.5.tgz#0b0225ee90362f030efd644e8034c99468893b08" @@ -274,13 +281,6 @@ dependencies: "@babel/types" "^7.28.5" -"@babel/parser@^7.28.6", "@babel/parser@^7.29.0": - version "7.29.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.2.tgz#58bd50b9a7951d134988a1ae177a35ef9a703ba1" - integrity sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA== - dependencies: - "@babel/types" "^7.29.0" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.28.5": version "7.28.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz#fbde57974707bbfa0376d34d425ff4fa6c732421" @@ -1101,6 +1101,14 @@ resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz#333fedabc3fd1a8e5d0100013731cf19e6a8c5d3" integrity sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw== +"@dependents/detective-less@^5.0.1": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@dependents/detective-less/-/detective-less-5.0.2.tgz#60e96bd9597bc2604295cb476448aa4192fa0215" + integrity sha512-QPKO4ao2+iniYAYnPZwHKK67EgDG2GAdye9OCy11xsmApHGwzpH3AcSdPjGyPO3tC2/K8mF7JjWX3A/FTRnskg== + dependencies: + gonzales-pe "^4.3.0" + node-source-walk "^7.0.1" + "@discoveryjs/json-ext@0.5.7": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" @@ -1596,7 +1604,7 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" -"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": version "1.5.5" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== @@ -2466,6 +2474,33 @@ dependencies: form-data "^4.0.4" +"@ts-graphviz/adapter@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@ts-graphviz/adapter/-/adapter-2.0.6.tgz#18d5a42304dca7ffff760fcaf311a3148ef4a3bd" + integrity sha512-kJ10lIMSWMJkLkkCG5gt927SnGZcBuG0s0HHswGzcHTgvtUe7yk5/3zTEr0bafzsodsOq5Gi6FhQeV775nC35Q== + dependencies: + "@ts-graphviz/common" "^2.1.5" + +"@ts-graphviz/ast@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@ts-graphviz/ast/-/ast-2.0.7.tgz#4ec33492e4b4e998d4632030e97a9f7e149afb86" + integrity sha512-e6+2qtNV99UT6DJSoLbHfkzfyqY84aIuoV8Xlb9+hZAjgpum8iVHprGeAMQ4rF6sKUAxrmY8rfF/vgAwoPc3gw== + dependencies: + "@ts-graphviz/common" "^2.1.5" + +"@ts-graphviz/common@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@ts-graphviz/common/-/common-2.1.5.tgz#a256dfaea009a5b147d8f73f25e57fb44f6462a2" + integrity sha512-S6/9+T6x8j6cr/gNhp+U2olwo1n0jKj/682QVqsh7yXWV6ednHYqxFw0ZsY3LyzT0N8jaZ6jQY9YD99le3cmvg== + +"@ts-graphviz/core@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@ts-graphviz/core/-/core-2.0.7.tgz#2185e390990038b267a2341c3db1cef3680bbee8" + integrity sha512-w071DSzP94YfN6XiWhOxnLpYT3uqtxJBDYdh6Jdjzt+Ce6DNspJsPQgpC7rbts/B8tEkq0LHoYuIF/O5Jh5rPg== + dependencies: + "@ts-graphviz/ast" "^2.0.7" + "@ts-graphviz/common" "^2.1.5" + "@tybys/wasm-util@^0.10.0": version "0.10.1" resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" @@ -2652,6 +2687,15 @@ "@typescript-eslint/types" "^8.58.2" debug "^4.4.3" +"@typescript-eslint/project-service@8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.59.0.tgz#914bf62069d870faa0389ffd725774a200f511bf" + integrity sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.59.0" + "@typescript-eslint/types" "^8.59.0" + debug "^4.4.3" + "@typescript-eslint/scope-manager@8.57.1", "@typescript-eslint/scope-manager@^8.56.0": version "8.57.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.57.1.tgz#4524d7e7b420cb501807499684d435ae129aaf35" @@ -2678,6 +2722,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.2.tgz#fa13f96432c9348bf87f6f44826def585fad7bca" integrity sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A== +"@typescript-eslint/tsconfig-utils@8.59.0", "@typescript-eslint/tsconfig-utils@^8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.0.tgz#1276077f5ad77e384446ea28a2474e8f8be1af41" + integrity sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg== + "@typescript-eslint/types@8.57.1", "@typescript-eslint/types@^8.57.1": version "8.57.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.57.1.tgz#54b27a8a25a7b45b4f978c3f8e00c4c78f11142c" @@ -2688,6 +2737,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.58.2.tgz#3ab8051de0f19a46ddefb0749d0f7d82974bd57c" integrity sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ== +"@typescript-eslint/types@8.59.0", "@typescript-eslint/types@^8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.59.0.tgz#cfcc643c6e879016479775850d86d84c14492738" + integrity sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A== + "@typescript-eslint/typescript-estree@8.57.1": version "8.57.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.1.tgz#a9fd28d4a0ec896aa9a9a7e0cead62ea24f99e76" @@ -2718,6 +2772,21 @@ tinyglobby "^0.2.15" ts-api-utils "^2.5.0" +"@typescript-eslint/typescript-estree@^8.58.2": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.0.tgz#feba58a70ab6ea7ac53a2f3ae900db28ce3454c2" + integrity sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw== + dependencies: + "@typescript-eslint/project-service" "8.59.0" + "@typescript-eslint/tsconfig-utils" "8.59.0" + "@typescript-eslint/types" "8.59.0" + "@typescript-eslint/visitor-keys" "8.59.0" + debug "^4.4.3" + minimatch "^10.2.2" + semver "^7.7.3" + tinyglobby "^0.2.15" + ts-api-utils "^2.5.0" + "@typescript-eslint/utils@^8.0.0": version "8.58.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.58.2.tgz#27165554a02d1ff57d98262fa92060498dabc8b3" @@ -2754,6 +2823,14 @@ "@typescript-eslint/types" "8.58.2" eslint-visitor-keys "^5.0.0" +"@typescript-eslint/visitor-keys@8.59.0": + version "8.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.0.tgz#2e80de30e7e944ed4bd47d751e37dcb04db03795" + integrity sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q== + dependencies: + "@typescript-eslint/types" "8.59.0" + eslint-visitor-keys "^5.0.0" + "@ungap/structured-clone@^1.2.0", "@ungap/structured-clone@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" @@ -2856,6 +2933,53 @@ resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== +"@vue/compiler-core@3.5.33": + version "3.5.33" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.33.tgz#69da5fdbeadb86d5a8511cf4b80e6116c21e00f6" + integrity sha512-3PZLQwFw4Za3TC8t0FvTy3wI16Kt+pmwcgNZca4Pj9iWL2E72a/gZlpBtAJvEdDMdCxdG/qq0C7PN0bsJuv0Rw== + dependencies: + "@babel/parser" "^7.29.2" + "@vue/shared" "3.5.33" + entities "^7.0.1" + estree-walker "^2.0.2" + source-map-js "^1.2.1" + +"@vue/compiler-dom@3.5.33": + version "3.5.33" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.33.tgz#20ec1f3b4d9c455cc90957e13767cd3ee16c9790" + integrity sha512-PXq0yrfCLzzL07rbXO4awtXY1Z06LG2eu6Adg3RJFa/j3Cii217XxxLXG22N330gw7GmALCY0Z8RgXEviwgpjA== + dependencies: + "@vue/compiler-core" "3.5.33" + "@vue/shared" "3.5.33" + +"@vue/compiler-sfc@^3.5.32": + version "3.5.33" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.33.tgz#647b0337dbef6e3da042576f5663ff327f635f78" + integrity sha512-UTUvRO9cY+rROrx/pvN9P5Z7FgA6QGfokUCfhQE4EnmUj3rVnK+CHI0LsEO1pg+I7//iRYMUfcNcCPe7tg0CoA== + dependencies: + "@babel/parser" "^7.29.2" + "@vue/compiler-core" "3.5.33" + "@vue/compiler-dom" "3.5.33" + "@vue/compiler-ssr" "3.5.33" + "@vue/shared" "3.5.33" + estree-walker "^2.0.2" + magic-string "^0.30.21" + postcss "^8.5.10" + source-map-js "^1.2.1" + +"@vue/compiler-ssr@3.5.33": + version "3.5.33" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.33.tgz#c4e98e9427b37585351f54cb105d4ccb477e572f" + integrity sha512-IErjYdnj1qIupG5xxiVIYiiRvDhGWV4zuh/RCrwfYpuL+HWQzeU6lCk/nF9r7olWMnjKxCAkOctT2qFWFkzb1A== + dependencies: + "@vue/compiler-dom" "3.5.33" + "@vue/shared" "3.5.33" + +"@vue/shared@3.5.33": + version "3.5.33" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.33.tgz#b41070039e91d2921edb4c38cbcc80f498a24f3a" + integrity sha512-5vR2QIlmaLG77Ygd4pMP6+SGQ5yox9VhtnbDWTy9DzMzdmeLxZ1QqxrywEZ9sa1AVubfIJyaCG3ytyWU81ufcQ== + "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" @@ -3121,6 +3245,11 @@ ansi-styles@^6.2.1, ansi-styles@^6.2.3: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== +any-promise@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + anymatch@^3.1.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -3129,6 +3258,11 @@ anymatch@^3.1.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +app-module-path@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" + integrity sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -3261,6 +3395,11 @@ asap@~2.0.3: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== +ast-module-types@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-6.0.1.tgz#4b4ca0251c57b815bab62604dcb22f8c903e2523" + integrity sha512-WHw67kLXYbZuHTmcdbIrVArCq5wxo6NEuj3hiYAWr8mwJeC+C2mMCIBIWCiDoCye/OF/xelc+teJ1ERoWmnEIA== + async-function@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" @@ -3403,6 +3542,11 @@ balanced-match@^4.0.2: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.4.tgz#bfb10662feed8196a2c62e7c68e17720c274179a" integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + baseline-browser-mapping@^2.9.0, baseline-browser-mapping@^2.9.15: version "2.10.19" resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.19.tgz#7697721c22f94f66195d0c34299b1a91e3299493" @@ -3413,6 +3557,15 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -3480,6 +3633,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" @@ -3534,7 +3695,7 @@ caniuse-lite@^1.0.30001759: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz#0e413de292808868a62ed9118822683fa120a110" integrity sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ== -chalk@^4.0.0, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3596,6 +3757,13 @@ clean-css@^5.2.2: dependencies: source-map "~0.6.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + cli-cursor@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" @@ -3603,6 +3771,11 @@ cli-cursor@^5.0.0: dependencies: restore-cursor "^5.0.0" +cli-spinners@^2.5.0: + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + cli-truncate@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-5.2.0.tgz#c8e72aaca8339c773d128c36e0a17c6315b694eb" @@ -3634,6 +3807,11 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + clsx@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" @@ -3661,7 +3839,7 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@~1.1.4: +color-name@^1.1.4, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== @@ -3713,6 +3891,11 @@ common-tags@1.8.2: resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -3912,6 +4095,11 @@ deep-diff@^1.0.2: resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-1.0.2.tgz#afd3d1f749115be965e89c63edc7abb1506b9c26" integrity sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg== +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -3922,6 +4110,13 @@ deepmerge@^4.3.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + define-data-property@^1.0.1, define-data-property@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" @@ -3945,6 +4140,16 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +dependency-tree@^11.0.0: + version "11.4.3" + resolved "https://registry.yarnpkg.com/dependency-tree/-/dependency-tree-11.4.3.tgz#573c5f2b55a711fd5cb63a249a3855cbceb76e1d" + integrity sha512-Y2gzOJ2Rb2X7MN6pT9llWpXxl5J5s5/11CBpJ5b85DjEqZH7jv3T9RO6HRV/PI/3MDmaKn/g7uoYdYmSb9vLlw== + dependencies: + commander "^12.1.0" + filing-cabinet "^5.3.0" + precinct "^12.3.1" + typescript "^5.9.3" + dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" @@ -3965,6 +4170,82 @@ detect-node-es@^1.1.0: resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== +detective-amd@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/detective-amd/-/detective-amd-6.0.2.tgz#2cc6eb5bc0ebad08ef5c307b1d1a972090acb6db" + integrity sha512-qX4zkNVcufOoo7pKlRnLHEzUwDcqIY5N9FEuNJN+rDUjct3gikNdVJXRfpI6sG/Y9pfIMjcXeNdHV1oYulxjmw== + dependencies: + ast-module-types "^6.0.1" + escodegen "^2.1.0" + get-amd-module-type "^6.0.1" + node-source-walk "^7.0.1" + +detective-cjs@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/detective-cjs/-/detective-cjs-6.1.1.tgz#b7c78b649dbdfa0bba228ab28c9707f4a04d5fd7" + integrity sha512-pSh7mkCKEtLlmANqLu3KDFS3NV8Hx41jy/JF1/gAWOgU+Uo5QTkeI1tWNP4dWGo4L0E9j18Ez9EPsTleautKqA== + dependencies: + ast-module-types "^6.0.1" + node-source-walk "^7.0.1" + +detective-es6@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/detective-es6/-/detective-es6-5.0.2.tgz#afca245be54cbb8bb316591b182cbf9bc8243dc0" + integrity sha512-+qHHGYhjupiVs4rnIpI9nZ5B130A4AmE35ZX1w33hb46vcZ7T3jfDbvmPw0FhWtMHn5BS5HHu7ZtnZ53bMcXZA== + dependencies: + node-source-walk "^7.0.1" + +detective-postcss@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/detective-postcss/-/detective-postcss-7.0.1.tgz#f5822d8988339fb56851fcdb079d51fbcff114db" + integrity sha512-bEOVpHU9picRZux5XnwGsmCN4+8oZo7vSW0O0/Enq/TO5R2pIAP2279NsszpJR7ocnQt4WXU0+nnh/0JuK4KHQ== + dependencies: + is-url "^1.2.4" + postcss-values-parser "^6.0.2" + +detective-sass@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/detective-sass/-/detective-sass-6.0.1.tgz#fcf5aa51bebf7b721807be418418470ee2409f8a" + integrity sha512-jSGPO8QDy7K7pztUmGC6aiHkexBQT4GIH+mBAL9ZyBmnUIOFbkfZnO8wPRRJFP/QP83irObgsZHCoDHZ173tRw== + dependencies: + gonzales-pe "^4.3.0" + node-source-walk "^7.0.1" + +detective-scss@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/detective-scss/-/detective-scss-5.0.1.tgz#6a7f792dc9c0e8cfc0d252a50ba26a6df12596a7" + integrity sha512-MAyPYRgS6DCiS6n6AoSBJXLGVOydsr9huwXORUlJ37K3YLyiN0vYHpzs3AdJOgHobBfispokoqrEon9rbmKacg== + dependencies: + gonzales-pe "^4.3.0" + node-source-walk "^7.0.1" + +detective-stylus@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/detective-stylus/-/detective-stylus-5.0.1.tgz#57d54a0b405305ee16655e42008b38a827a9f179" + integrity sha512-Dgn0bUqdGbE3oZJ+WCKf8Dmu7VWLcmRJGc6RCzBgG31DLIyai9WAoEhYRgIHpt/BCRMrnXLbGWGPQuBUrnF0TA== + +detective-typescript@^14.1.0, detective-typescript@^14.1.1: + version "14.1.2" + resolved "https://registry.yarnpkg.com/detective-typescript/-/detective-typescript-14.1.2.tgz#130208ab8d0d219931ae73947ce56814a462b6d3" + integrity sha512-bIeEn0eVi/JRsE1YizBR2ilnMlWRAIBJJ6kXCKNFxEEWhUcEY3R6I3KYIAy48ieURbD1hcb3Ebvl8AqeoPMSzg== + dependencies: + "@typescript-eslint/typescript-estree" "^8.58.2" + ast-module-types "^6.0.1" + node-source-walk "^7.0.1" + +detective-vue2@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/detective-vue2/-/detective-vue2-2.3.0.tgz#8e2029a96ef5dcfb57c5d9fe05ba2308d6ea2b8e" + integrity sha512-3gwbZPqVTm9sL9XdZsgEJ7x4x99O853VVZHapQAiEkGuMJMpFPjHDrecSgfqnS5JW3FJfYXesLZGvUOibjn49g== + dependencies: + "@dependents/detective-less" "^5.0.1" + "@vue/compiler-sfc" "^3.5.32" + detective-es6 "^5.0.1" + detective-sass "^6.0.1" + detective-scss "^5.0.1" + detective-stylus "^5.0.1" + detective-typescript "^14.1.0" + diff-match-patch@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37" @@ -4138,6 +4419,14 @@ enhanced-resolve@^5.17.4: graceful-fs "^4.2.4" tapable "^2.3.0" +enhanced-resolve@^5.20.0, enhanced-resolve@^5.20.1: + version "5.21.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz#bb8e6fabaf74930de70e61397798750429e5b1ae" + integrity sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.3.3" + entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -4148,6 +4437,11 @@ entities@^6.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== +entities@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-7.0.1.tgz#26e8a88889db63417dcb9a1e79a3f1bc92b5976b" + integrity sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA== + envinfo@^7.14.0: version "7.14.0" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" @@ -4310,6 +4604,17 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escodegen@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionalDependencies: + source-map "~0.6.1" + eslint-import-resolver-node@^0.3.9: version "0.3.9" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" @@ -4487,7 +4792,7 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" -esprima@^4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -4516,6 +4821,11 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -4684,6 +4994,23 @@ file-saver@^2.0.5: resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== +filing-cabinet@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/filing-cabinet/-/filing-cabinet-5.3.0.tgz#b9ab46a21fd733f42a05902bb0d317be93b03174" + integrity sha512-2EwtzdQkC37FJxDOrKuEOplTFzzaToCqzT008DrIWW27RQ6psxitfUi6hct5mUhMHO7C6xopOhxubyjyPCapbQ== + dependencies: + app-module-path "^2.2.0" + commander "^12.1.0" + enhanced-resolve "^5.20.1" + module-definition "^6.0.1" + module-lookup-amd "^9.1.1" + resolve "^1.22.12" + resolve-dependency-path "^4.0.1" + sass-lookup "^6.1.1" + stylus-lookup "^6.1.1" + tsconfig-paths "^4.2.0" + typescript "^5.9.3" + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -4841,6 +5168,14 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +get-amd-module-type@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/get-amd-module-type/-/get-amd-module-type-6.0.2.tgz#257604e956bc7ec3f48da209c8a7e5ba4470a2fa" + integrity sha512-7zShVYAYtMnj9S65CfN+hvpBCByfuB1OY8xID01nZEzXTZbx4YyysAfi+nMl95JSR6odt4q8TCj2W63KAoyVLQ== + dependencies: + ast-module-types "^6.0.1" + node-source-walk "^7.0.1" + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -4872,6 +5207,11 @@ get-nonce@^1.0.0: resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -4995,6 +5335,13 @@ globby@^10.0.1: merge2 "^1.2.3" slash "^3.0.0" +gonzales-pe@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3" + integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ== + dependencies: + minimist "^1.2.5" + gopd@^1.0.1, gopd@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" @@ -5172,6 +5519,11 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.1.1, ignore@^5.2.0: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" @@ -5231,7 +5583,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2: +inherits@2, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -5241,6 +5593,11 @@ ini@^5.0.0: resolved "https://registry.yarnpkg.com/ini/-/ini-5.0.0.tgz#a7a4615339843d9a8ccc2d85c9d81cf93ffbc638" integrity sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw== +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + internal-slot@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" @@ -5384,6 +5741,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-lite@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/is-lite/-/is-lite-0.8.2.tgz#26ab98b32aae8cc8b226593b9a641d2bf4bd3b6a" @@ -5422,6 +5784,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== + is-path-inside@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" @@ -5449,6 +5816,11 @@ is-regex@^1.2.1: has-tostringtag "^1.0.2" hasown "^2.0.2" +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== + is-set@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" @@ -5490,6 +5862,21 @@ is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: dependencies: which-typed-array "^1.1.16" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-url-superb@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-url-superb/-/is-url-superb-4.0.0.tgz#b54d1d2499bb16792748ac967aa3ecb41a33a8c2" + integrity sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA== + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + is-weakmap@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" @@ -6085,7 +6472,7 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.2.3: +json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -6241,6 +6628,14 @@ lodash@^4.17.20, lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + log-update@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.1.0.tgz#1a04ff38166f94647ae1af562f4bd6a15b1b7cd4" @@ -6298,6 +6693,24 @@ lz-string@^1.5.0: resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== +madge@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/madge/-/madge-8.0.0.tgz#cca4ab66fb388e7b6bf43c1f78dcaab3cad30f50" + integrity sha512-9sSsi3TBPhmkTCIpVQF0SPiChj1L7Rq9kU2KDG1o6v2XH9cCw086MopjVCD+vuoL5v8S77DTbVopTO8OUiQpIw== + dependencies: + chalk "^4.1.2" + commander "^7.2.0" + commondir "^1.0.1" + debug "^4.3.4" + dependency-tree "^11.0.0" + ora "^5.4.1" + pluralize "^8.0.0" + pretty-ms "^7.0.1" + rc "^1.2.8" + stream-to-array "^2.3.0" + ts-graphviz "^2.1.2" + walkdir "^0.4.1" + magic-string@0.30.8: version "0.30.8" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.8.tgz#14e8624246d2bedba70d5462aa99ac9681844613" @@ -6305,6 +6718,13 @@ magic-string@0.30.8: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" +magic-string@^0.30.21: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + make-dir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" @@ -6410,7 +6830,7 @@ minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.0, minimist@^1.2.6: +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -6420,6 +6840,23 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== +module-definition@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/module-definition/-/module-definition-6.0.2.tgz#d72a3613dbf6fe7247ebef64f11fddc2cd18b83b" + integrity sha512-SvAU3lB0+Yjbq55yHY3wkRZBOh+fhU1SnIF3IFbTewv6mtAh7yUT8ACHAJ2mGIJ7tCes2QuCL/cl6m0JSZ/ArA== + dependencies: + ast-module-types "^6.0.1" + node-source-walk "^7.0.1" + +module-lookup-amd@^9.1.1: + version "9.1.2" + resolved "https://registry.yarnpkg.com/module-lookup-amd/-/module-lookup-amd-9.1.2.tgz#8fd7da50219f780e47a329b3da43a5082c5c7c76" + integrity sha512-HFEiUNm8/woZFJZcd42wrovEHjHN6nwfNjf2CjiVLbVFRbj+sEmEJn0mrx8JY4/qJP8wSZTtmguikAJBqEuRRQ== + dependencies: + commander "^12.1.0" + requirejs "^2.3.8" + requirejs-config-file "^4.0.0" + moment@^2.29.4: version "2.30.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" @@ -6514,6 +6951,13 @@ node-releases@^2.0.27: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.36.tgz#99fd6552aaeda9e17c4713b57a63964a2e325e9d" integrity sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA== +node-source-walk@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-7.0.1.tgz#3e4ab8d065377228fd038af7b2d4fb58f61defd3" + integrity sha512-3VW/8JpPqPvnJvseXowjZcirPisssnBuDikk6JIZ8jQzF7KJQX52iPFX4RYYxLycYH7IbMRSPUOga/esVjy5Yg== + dependencies: + "@babel/parser" "^7.26.7" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -6616,7 +7060,7 @@ once@^1.3.0: dependencies: wrappy "1" -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -6647,6 +7091,21 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + outvariant@^1.4.0, outvariant@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" @@ -6744,6 +7203,11 @@ parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse-ms@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" + integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== + parse5@^7.0.0, parse5@^7.2.1: version "7.3.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05" @@ -6842,6 +7306,11 @@ platform@1.3.6: resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + popper.js@^1.16.0: version "1.16.1" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" @@ -6915,6 +7384,15 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== +postcss-values-parser@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-6.0.2.tgz#636edc5b86c953896f1bb0d7a7a6615df00fb76f" + integrity sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw== + dependencies: + color-name "^1.1.4" + is-url-superb "^4.0.0" + quote-unquote "^1.0.0" + postcss@^8.4.40: version "8.5.6" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" @@ -6924,6 +7402,15 @@ postcss@^8.4.40: picocolors "^1.1.1" source-map-js "^1.2.1" +postcss@^8.5.10: + version "8.5.10" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.10.tgz#8992d8c30acf3f12169e7c09514a12fed7e48356" + integrity sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + posthog-js@^1.57.2: version "1.369.2" resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.369.2.tgz#e11f736f925cf94c827ee97fd9565a861797cec0" @@ -6948,6 +7435,27 @@ preact@^10.28.2: resolved "https://registry.yarnpkg.com/preact/-/preact-10.29.1.tgz#2a5b936efe91cfe1e773cdb55dceb55d148d1d4b" integrity sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg== +precinct@^12.3.1: + version "12.3.1" + resolved "https://registry.yarnpkg.com/precinct/-/precinct-12.3.1.tgz#8d9eb1afa9537917092402d11b34aeab5236fbeb" + integrity sha512-wGyTIvtxh2S2NAHxTJj0YymxWOIcEDotu17yHoQUd2Bz2C07LrS28L1nvXDMxrCHvHmV6KTlaIQy5PzRm7Y8rg== + dependencies: + "@dependents/detective-less" "^5.0.1" + commander "^12.1.0" + detective-amd "^6.0.1" + detective-cjs "^6.1.0" + detective-es6 "^5.0.1" + detective-postcss "^7.0.1" + detective-sass "^6.0.1" + detective-scss "^5.0.1" + detective-stylus "^5.0.1" + detective-typescript "^14.1.1" + detective-vue2 "^2.3.0" + module-definition "^6.0.1" + node-source-walk "^7.0.1" + postcss "^8.5.10" + typescript "^5.9.3" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -6984,6 +7492,13 @@ pretty-format@^27.0.2: ansi-styles "^5.0.0" react-is "^17.0.1" +pretty-ms@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-7.0.1.tgz#7d903eaab281f7d8e03c66f867e239dc32fb73e8" + integrity sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q== + dependencies: + parse-ms "^2.1.0" + progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -7048,6 +7563,21 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quote-unquote@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/quote-unquote/-/quote-unquote-1.0.0.tgz#67a9a77148effeaf81a4d428404a710baaac8a0b" + integrity sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg== + +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-datepicker@^8.0.0: version "8.10.0" resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-8.10.0.tgz#dfc4534afde70b491883085d8df959b25689d10f" @@ -7202,6 +7732,15 @@ react@^18.0.0: dependencies: loose-envify "^1.1.0" +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@^4.0.1: version "4.1.2" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" @@ -7327,6 +7866,19 @@ requireindex@^1.2.0: resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef" integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== +requirejs-config-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/requirejs-config-file/-/requirejs-config-file-4.0.0.tgz#4244da5dd1f59874038cc1091d078d620abb6ebc" + integrity sha512-jnIre8cbWOyvr8a5F2KuqBnY+SDA4NXr/hzEZJG79Mxm2WiFQz2dzhC8ibtPJS7zkmBEl1mxSwp5HhC1W4qpxw== + dependencies: + esprima "^4.0.0" + stringify-object "^3.2.1" + +requirejs@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.8.tgz#bca0614b618ab2122462597e44878db7558bbba3" + integrity sha512-7/cTSLOdYkNBNJcDMWf+luFvMriVm7eYxp4BcFCsAX0wF421Vyce5SXP17c+Jd5otXKGNehIonFlyQXSowL6Mw== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -7334,6 +7886,11 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-dependency-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/resolve-dependency-path/-/resolve-dependency-path-4.0.1.tgz#1b9d43e5b62384301e26d040b9fce61ee5db60bd" + integrity sha512-YQftIIC4vzO9UMhO/sCgXukNyiwVRCVaxiWskCBy7Zpqkplm8kTAISZ8O1MoKW1ca6xzgLUBjZTcDgypXvXxiQ== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -7362,6 +7919,16 @@ resolve@^1.22.11: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.22.12: + version "1.22.12" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.12.tgz#f5b2a680897c69c238a13cd16b15671f8b73549f" + integrity sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA== + dependencies: + es-errors "^1.3.0" + is-core-module "^2.16.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.5: version "2.0.0-next.5" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" @@ -7371,6 +7938,14 @@ resolve@^2.0.0-next.5: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + restore-cursor@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" @@ -7424,6 +7999,11 @@ safe-array-concat@^1.1.3: has-symbols "^1.1.0" isarray "^2.0.5" +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-push-apply@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" @@ -7453,6 +8033,14 @@ sass-loader@16.0.7: dependencies: neo-async "^2.6.2" +sass-lookup@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-6.1.1.tgz#1e0eeef27fff868b460ce833914cba9c11bc2866" + integrity sha512-12dvZdQYTeKZ1ypjuiijZYuMZ1m0F+4+BkRX5yJi2WA9W3DBUrcdCt7bVuKlagHl11n8eYtalWDle+m98Ol2DA== + dependencies: + commander "^12.1.0" + enhanced-resolve "^5.20.0" + sass@^1.66.0: version "1.94.2" resolved "https://registry.yarnpkg.com/sass/-/sass-1.94.2.tgz#198511fc6fdd2fc0a71b8d1261735c12608d4ef3" @@ -7648,7 +8236,7 @@ side-channel@^1.1.0: side-channel-map "^1.0.1" side-channel-weakmap "^1.0.2" -signal-exit@^3.0.3: +signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -7767,6 +8355,13 @@ stop-iteration-iterator@^1.1.0: es-errors "^1.3.0" internal-slot "^1.1.0" +stream-to-array@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" + integrity sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA== + dependencies: + any-promise "^1.1.0" + strict-event-emitter@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" @@ -7884,6 +8479,22 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +stringify-object@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== + dependencies: + get-own-enumerable-property-symbols "^3.0.0" + is-obj "^1.0.1" + is-regexp "^1.0.0" + "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -7939,6 +8550,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + style-inject@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/style-inject/-/style-inject-0.3.0.tgz#d21c477affec91811cc82355832a700d22bf8dd3" @@ -7949,6 +8565,13 @@ style-loader@4.0.0: resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-4.0.0.tgz#0ea96e468f43c69600011e0589cb05c44f3b17a5" integrity sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA== +stylus-lookup@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-6.1.1.tgz#0ded653fde0cdc408d7c51ea240eeacc0dd404c1" + integrity sha512-0+xmFLaqWksv5/pMiZtONG6gP82YNGVWgKiQXvw8cdKVFEJ++X9dySGR0hG+A+78PBtbHPqiJzXi2ZKoWr/7Sg== + dependencies: + commander "^12.1.0" + substyle@^9.1.0: version "9.4.1" resolved "https://registry.yarnpkg.com/substyle/-/substyle-9.4.1.tgz#6a4647f363bc14fecc51aac371d4dbeda082aa50" @@ -8003,6 +8626,11 @@ tapable@^2.0.0, tapable@^2.2.1, tapable@^2.3.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.0.tgz#7e3ea6d5ca31ba8e078b560f0d83ce9a14aa8be6" integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg== +tapable@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.3.tgz#5da7c9992c46038221267985ab28421a8879f160" + integrity sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A== + terser-webpack-plugin@^5.3.11, terser-webpack-plugin@^5.3.16: version "5.4.0" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz#95fc4cf4437e587be11ecf37d08636089174d76b" @@ -8158,6 +8786,16 @@ ts-api-utils@^2.4.0, ts-api-utils@^2.5.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz#4acd4a155e22734990a5ed1fe9e97f113bcb37c1" integrity sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA== +ts-graphviz@^2.1.2: + version "2.1.6" + resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-2.1.6.tgz#007fcb42b4e8c55d26543ece9e86395bd3c3cfd6" + integrity sha512-XyLVuhBVvdJTJr2FJJV2L1pc4MwSjMhcunRVgDE9k4wbb2ee7ORYnPewxMWUav12vxyfUM686MSGsqnVRIInuw== + dependencies: + "@ts-graphviz/adapter" "^2.0.6" + "@ts-graphviz/ast" "^2.0.7" + "@ts-graphviz/common" "^2.1.5" + "@ts-graphviz/core" "^2.0.7" + tsconfig-paths@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -8168,6 +8806,15 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" +tsconfig-paths@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" @@ -8252,6 +8899,11 @@ typed-array-length@^1.0.7: possible-typed-array-names "^1.0.0" reflect.getprototypeof "^1.0.6" +typescript@^5.9.3: + version "5.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== + ua-parser-js@^0.7.18: version "0.7.40" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.40.tgz#c87d83b7bb25822ecfa6397a0da5903934ea1562" @@ -8394,7 +9046,7 @@ use-sidecar@^1.1.3: detect-node-es "^1.1.0" tslib "^2.0.0" -util-deprecate@^1.0.2: +util-deprecate@^1.0.1, util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -8430,6 +9082,11 @@ w3c-xmlserializer@^5.0.0: dependencies: xml-name-validator "^5.0.0" +walkdir@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.4.1.tgz#dc119f83f4421df52e3061e514228a2db20afa39" + integrity sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ== + walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -8452,6 +9109,13 @@ watchpack@^2.4.4: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + web-streams-polyfill@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.2.0.tgz#93295e67af95889a1e044a6beff1366c82720650"