Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
b74d5a3
chore: add madge circular dependency baseline and regression check
riccio82 Apr 24, 2026
343deba
refactor: replace action→component imports with modal registry and st…
riccio82 Apr 24, 2026
a45df16
refactor: extract settingsPanel contexts, utils, and constants into s…
riccio82 Apr 24, 2026
1897bcb
refactor: extract parent→child constants and break DraftMatecatUtils …
riccio82 Apr 24, 2026
13b1c43
refactor: extract htmlUtils from tagUtils to break DraftMatecatUtils …
riccio82 Apr 24, 2026
18fcd91
refactor: lazy-require 7 cycle-forming imports in SegmentActions
riccio82 Apr 24, 2026
2605b8b
refactor: lazy-require cycle-forming imports in SegmentStore, commonU…
riccio82 Apr 24, 2026
5745e95
refactor: lazy-require OfflineUtils in CatToolActions to break final …
riccio82 Apr 24, 2026
b666d37
chore: update circular dependency baseline to 0 cycles
riccio82 Apr 24, 2026
135b467
🔧 chore: simplify circular dependency checker and remove baseline
riccio82 Apr 24, 2026
1c58157
🐛 fix(cattool): import TAB constant in SegmentFooter
riccio82 Apr 24, 2026
b3086e9
🐛 fix(settings-panel): fix test failures from circular dep refactoring
riccio82 Apr 24, 2026
97c930e
♻️ refactor(imports): remove dead re-exports and redirect consumers t…
riccio82 Apr 27, 2026
8034f07
♻️ refactor(imports): remove remaining dead re-exports and unused imp…
riccio82 Apr 27, 2026
fd5e68f
♻️ refactor(imports): extract leaf modules from SegmentActions to eli…
riccio82 Apr 27, 2026
ae4fe8c
♻️ refactor(imports): convert SS→DMU and CU→OU lazy requires to stati…
riccio82 Apr 28, 2026
64a2080
Update public/js/components/createProject/UploadFileUtils.js
riccio82 Apr 28, 2026
eaf3043
🔧 chore(deps): update @translated/lara to 1.9.0 (#4516)
riccio82 Apr 27, 2026
5569a91
feat: add ed error_code to AI Worker messages (#4533)
mauretto78 Apr 27, 2026
cd42fe4
🔧 chore(phpstan): regenerate baseline for new @throws rules
Ostico Apr 20, 2026
f2095c2
📝 docs: add PR readiness checklist template and GitHub Actions validator
Ostico Apr 20, 2026
5e6ceef
📝 docs(pr-template): simplify AI usage disclosure instructions
Ostico Apr 20, 2026
6781d04
🔧 chore(jest): exclude .github/ from Jest test discovery
Ostico Apr 20, 2026
581eede
🔧 chore(phpstan): exclude APIDoc build artifacts from analysis
Ostico Apr 20, 2026
44204c5
Update .github/workflows/pr-readiness-check.yml
Ostico Apr 20, 2026
5fbcc06
👷 ci: add conventional-commit message enforcement workflow
Ostico Apr 20, 2026
660f4f8
🐛 fix(ci): relax commit message check for Copilot and GitHub web edits
Ostico Apr 20, 2026
b63af4a
🔧 chore(phpstan): add @throws \Throwable to FastAnalysis transaction …
Ostico Apr 21, 2026
1543065
👷 ci(test-guard): add test adequacy gate workflow
Ostico Apr 21, 2026
0f81ee7
👷 ci(test-guard): integrate test-guard into CI/CD pipeline
Ostico Apr 21, 2026
fe52a90
👷 ci(test-guard): bump ostico/test-guard to v1.0.3
Ostico Apr 21, 2026
f57837f
👷 ci(test-guard): bump ostico/test-guard to v1.0.5
Ostico Apr 21, 2026
f065dce
👷 ci: add models:read permission to _ci-cd.yml
Ostico Apr 21, 2026
06b4f21
🐛 fix(ci): add models:read permission for test-guard AI analysis
Ostico Apr 21, 2026
4384a3d
👷 ci(test-guard): switch to floating tag ostico/test-guard@v1
Ostico Apr 21, 2026
768512e
👷 ci(permissions): replace statuses:write with checks:write in workflows
Ostico Apr 22, 2026
de174e5
👷 ci(coverage): add JS coverage report to test-guard pipeline
Ostico Apr 23, 2026
d8d0ebb
Update submodule
riccio82 Apr 28, 2026
fd4ac5c
Merge remote-tracking branch 'origin/develop' into fix/circular-deps
Copilot Apr 28, 2026
f33830f
Merge remote-tracking branch 'origin/develop' into fix/circular-deps
riccio82 Apr 28, 2026
b4b6702
🐛 fix(modals): replace undefined AlertModal with MODAL_KEY.ALERT cons…
riccio82 Apr 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions check-circular-deps.js
Original file line number Diff line number Diff line change
@@ -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/',
Comment thread
riccio82 marked this conversation as resolved.
{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')
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion plugins/airbnb
Submodule airbnb updated 0 files
2 changes: 1 addition & 1 deletion plugins/translated
2 changes: 1 addition & 1 deletion plugins/uber
Submodule uber updated from c6beac to cc5299
2 changes: 1 addition & 1 deletion public/img/icons/ChangePassword.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
const ChangePassword = ({size = 24}) => {
return (
<svg width={size} height={size} viewBox="0 0 16 16" fill="none">
<g fill="currentColor" clip-path="url(#a)">
<g fill="currentColor" clipPath="url(#a)">
<path d="M10 8.747c0-.235 0-.372-.009-.474a.613.613 0 0 0-.01-.083.118.118 0 0 0-.035-.04.605.605 0 0 0-.055-.008 5.923 5.923 0 0 0-.444-.009H6.552c-.225 0-.351.001-.443.01a.614.614 0 0 0-.056.006.12.12 0 0 0-.034.041.615.615 0 0 0-.011.083C6 8.375 6 8.513 6 8.747v.64c0 .234 0 .372.008.473a.62.62 0 0 0 .01.083l.021.03.015.011c.01.002.027.006.055.008.092.008.218.008.443.008h2.895c.225 0 .352 0 .444-.008.026-.002.043-.006.054-.008.004-.003.01-.006.015-.012l.02-.029a.616.616 0 0 0 .011-.083 6.93 6.93 0 0 0 .01-.474v-.64Zm-1.334-2.68c0-.436-.328-.733-.666-.733s-.667.297-.667.733V6.8h1.333v-.733ZM10 6.812l.005.001c.128.011.27.033.415.087l.145.066.1.058c.224.145.402.35.518.588.093.192.124.385.137.558.013.165.013.363.013.577v.64c0 .213 0 .411-.013.577a1.522 1.522 0 0 1-.137.557 1.45 1.45 0 0 1-.618.647 1.417 1.417 0 0 1-.56.152c-.162.014-.356.014-.558.014H6.552c-.202 0-.395 0-.557-.014a1.42 1.42 0 0 1-.56-.152 1.45 1.45 0 0 1-.618-.647 1.522 1.522 0 0 1-.138-.557c-.013-.166-.013-.364-.013-.578v-.64c0-.213 0-.411.013-.576.013-.173.044-.366.138-.558.132-.273.347-.5.618-.646L5.58 6.9c.145-.054.287-.076.415-.087H6v-.746C6 4.957 6.865 4 8 4s2 .957 2 2.067v.745Z" />
<path d="M11.317 13.371a.75.75 0 0 1-.382.99 6.743 6.743 0 0 1-9.05-8.55l-.203.054a.75.75 0 0 1-.388-1.45L3.222 3.9l.146-.024a.752.752 0 0 1 .773.555l.516 1.927a.75.75 0 1 1-1.449.388l-.025-.096a5.243 5.243 0 0 0 7.145 6.34.75.75 0 0 1 .989.382Zm.254-11.018a6.743 6.743 0 0 1 2.936 8.228l.202-.053a.751.751 0 0 1 .389 1.448l-1.928.517a.751.751 0 0 1-.919-.53l-.516-1.928a.75.75 0 1 1 1.449-.387l.025.094a5.244 5.244 0 0 0-7.144-6.34.75.75 0 1 1-.608-1.37 6.74 6.74 0 0 1 6.114.32Z" />
</g>
Expand Down
48 changes: 18 additions & 30 deletions public/js/actions/CatToolActions.js
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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,
Expand Down Expand Up @@ -121,7 +124,7 @@ let CatToolActions = {
},
}
ModalsActions.showModalComponent(
RevisionFeedbackModal,
MODAL_KEY.REVISION_FEEDBACK,
props,
'Feedback submission',
)
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -313,7 +301,7 @@ let CatToolActions = {
},
}
ModalsActions.showModalComponent(
ConfirmMessageModal,
MODAL_KEY.CONFIRM_MESSAGE,
props,
'Lara Free Plan Limit Reached',
)
Expand Down Expand Up @@ -356,7 +344,7 @@ let CatToolActions = {

//check for errors
if (data.details) {
SegmentActions.updateGlobalWarnings(data.details)
updateGlobalWarnings(data.details)
}
CommonUtils.dispatchCustomEvent('getWarning:global:success')
})
Expand All @@ -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.<br />Refresh the page to update segment status.',
buttonText: 'Refresh page',
Expand All @@ -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: <br />1) Refresh the page (Ctrl+F5 twice) <br />2) Clear the cache in the browser <br />If the solutions above does not resolve the issue, please stop the translation and report the problem to <b>support@matecat.com</b>',
},
Expand All @@ -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,
Expand All @@ -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.</br>' +
Expand Down
11 changes: 7 additions & 4 deletions public/js/actions/CatToolActions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
}))
Expand All @@ -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(() => {
Expand All @@ -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.<br />Refresh the page to update segment status.',
buttonText: 'Refresh page',
Expand All @@ -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'),
}),
Expand All @@ -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),
Expand Down
34 changes: 16 additions & 18 deletions public/js/actions/ModalsActions.js
Original file line number Diff line number Diff line change
@@ -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: (
Expand All @@ -35,7 +29,7 @@ let ModalsActions = {
},
openLoginModal: function () {
ModalsActions.showModalComponent(
OnBoarding,
MODAL_KEY.ONBOARDING,
{isCloseButtonEnabled: true},
null,
{maxWidth: 'unset', width: 'auto'},
Expand All @@ -46,7 +40,7 @@ let ModalsActions = {
},
openRegisterModal: () => {
ModalsActions.showModalComponent(
OnBoarding,
MODAL_KEY.ONBOARDING,
{
step: ONBOARDING_STEP.REGISTER,
isCloseButtonEnabled: true,
Expand All @@ -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
Expand All @@ -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) {
Expand All @@ -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 = {
Expand All @@ -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 (
Expand All @@ -142,7 +140,7 @@ let ModalsActions = {
cancelCallback,
) {
ModalsActions.showModalComponent(
DownloadAlertModal,
MODAL_KEY.DOWNLOAD_ALERT,
{successCallback, successCallbackWithoutErrors, cancelCallback},
'Unresolved Major Issues',
)
Expand Down
Loading
Loading