Skip to content

fix: move media file type list page and edit into MUI components#897

Open
tomrndom wants to merge 3 commits into
masterfrom
fix/migrate-media-file-type-list
Open

fix: move media file type list page and edit into MUI components#897
tomrndom wants to merge 3 commits into
masterfrom
fix/migrate-media-file-type-list

Conversation

@tomrndom
Copy link
Copy Markdown

@tomrndom tomrndom commented Apr 24, 2026

ref: https://app.clickup.com/t/86b9jqczj

image image

Signed-off-by: Tomás Castillo tcastilloboireau@gmail.com

Summary by CodeRabbit

  • New Features

    • In-page dialog for creating/editing media file types with validation and save behavior
    • Updated delete confirmation to include the item name
  • Refactor

    • List UI migrated to Material UI with improved search, pagination, and per-page handling
    • Save/delete flows now show snackbar notifications and have consistent loading cleanup; edit is now in-dialog (no separate edit page)
  • Tests

    • Added comprehensive tests for the list page and dialog component

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

Refactors media file type management: class -> hooks-based list page with in-page dialog, unified snackbar-based error/success handlers in actions, loader cleanup moved to .finally, reducer/pagination state tweaks, new unit tests, layout route cleanup, and updated delete i18n.

Changes

Media File Types

Layer / File(s) Summary
Action creators: snackbar handlers & loader cleanup
src/actions/media-file-type-actions.js
Replaced authErrorHandler/message utils with snackbarErrorHandler/snackbarSuccessHandler across requests; moved loader cleanup to .finally; saveMediaFileType signature now (entity) and always dispatches snackbar success on save.
Dialog component
src/pages/media_file_types/components/media-file-type-dialog.js
Added MediaFileTypeDialog default export: Formik-based MUI dialog, validates name, converts allowed_extensions array↔CSV string, resets on close, and disables controls while saving.
List Page
src/pages/media_file_types/media-file-type-list-page.js
Converted to functional hooks component using MUI (Grid2, MuiTable, SearchInput); in-page dialog for add/edit; wired getMediaFileType, saveMediaFileType, resetMediaFileTypeForm; table-driven delete confirmation and refreshed list flows.
Layout & Routes
src/layouts/media-file-type-layout.js
Refactored to functional layout and removed separate edit routes; retains breadcrumb and base list route.
Tests
src/pages/media_file_types/__tests__/media-file-type-list-page.test.js, src/pages/media_file_types/components/__tests__/media-file-type-dialog.test.js
Added RTL/Jest tests covering mount dispatch, empty/non-empty rendering, add/edit/delete flows, search behavior, dialog validation, and save callbacks.
i18n
src/i18n/en.json
Updated media_file_type.delete_warning to include {name} placeholder and a trailing question mark.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant List as MediaFileTypeListPage
    participant Dialog as MediaFileTypeDialog
    participant Actions as MediaFileTypeActions
    participant Reducer as MediaFileTypeReducer
    participant Snackbar as SnackbarHandler

    User->>List: Click "Edit" / "Add"
    List->>Actions: dispatch(getMediaFileType(id)) / resetMediaFileTypeForm
    Actions->>Reducer: REQUEST_MEDIA_FILE_TYPE
    Reducer-->>List: loading state
    Actions->>Reducer: RECEIVE_MEDIA_FILE_TYPE
    Reducer-->>List: entity loaded
    List->>Dialog: open with entity

    User->>Dialog: Submit form
    Dialog->>List: onSave(formData)
    List->>Actions: dispatch(saveMediaFileType(entity))
    Actions->>Reducer: REQUEST_SAVE_MEDIA_FILE_TYPE
    Reducer-->>List: loading
    Actions->>Actions: perform API request (snackbarErrorHandler used)
    Actions->>Snackbar: snackbarSuccessHandler / snackbarErrorHandler
    Snackbar-->>User: show notification
    Actions->>Reducer: RECEIVE_SAVE_MEDIA_FILE_TYPE
    Reducer-->>List: updated state
    List->>Actions: dispatch(getMediaFileTypes())
    List-->>User: refreshed list
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Suggested reviewers

  • smarcet
  • martinquiroga-exo
  • santipalenque

Poem

🐰 A dialog blooms where routes once led,
Formik hops through fields of text and thread,
Snackbars chirp secrets—success or whoops!—in view,
Hooks bind the list and fetch a fresher crew,
Tiny rabbit claps: refactor—done—pursue!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: migrating the media file type list and edit pages to MUI components, which is the primary focus of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/migrate-media-file-type-list

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/actions/media-file-type-actions.js (1)

211-212: ⚠️ Potential issue | 🟠 Major

Normalize and filter allowed_extensions before sending.

An empty field currently becomes [""], and inputs like PDF, DOC keep the leading space on DOC. That can persist invalid extension values or trip backend validation.

Suggested fix
-  normalizedEntity.allowed_extensions = entity.allowed_extensions.split(",");
+  normalizedEntity.allowed_extensions = (entity.allowed_extensions ?? "")
+    .split(",")
+    .map((ext) => ext.trim())
+    .filter(Boolean);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/actions/media-file-type-actions.js` around lines 211 - 212, Update the
assignment that builds normalizedEntity.allowed_extensions so it trims
whitespace and removes empty entries: when entity.allowed_extensions exists,
split on "," then map each part with trim() and filter out empty strings (e.g.,
filter(Boolean)); if entity.allowed_extensions is falsy, set
normalizedEntity.allowed_extensions to an empty array. Locate the
normalizedEntity.allowed_extensions = entity.allowed_extensions.split(","); line
and replace it with this normalized-and-filtered logic to avoid values like ""
or " DOC".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pages/media_file_types/media-file-type-list-page.js`:
- Around line 74-99: The async UI handlers (handleRowEdit, handleSave,
handleDelete and similar) currently start promise chains without returning them
or adding terminal catches; update each to return the promise chain and attach a
.catch that routes errors to the existing snackbarErrorHandler (or otherwise
handles the error) so rejections are not unhandled; specifically: return
getMediaFileType(...) from handleRowEdit, return the reset/setOpen flows where
applicable, make handleSave return the
saveMediaFileType(...).then(getMediaFileTypes...).then(...).catch(snackbarErrorHandler)
so Formik can await it, and return
deleteMediaFileType(...).then(getMediaFileTypes...).catch(snackbarErrorHandler)
from handleDelete; keep using resetMediaFileTypeForm and setOpen as before but
ensure all chains are returned and terminally caught.
- Around line 186-187: The delete dialog is using the old i18n key
"media_file_type.remove_warning" so the translation is missing; update the
T.translate call inside the deleteDialogBody prop (currently
T.translate("media_file_type.remove_warning", { name })) to use the new key
"media_file_type.delete_warning" while keeping the { name } interpolation intact
so the localized message displays correctly.

---

Outside diff comments:
In `@src/actions/media-file-type-actions.js`:
- Around line 211-212: Update the assignment that builds
normalizedEntity.allowed_extensions so it trims whitespace and removes empty
entries: when entity.allowed_extensions exists, split on "," then map each part
with trim() and filter out empty strings (e.g., filter(Boolean)); if
entity.allowed_extensions is falsy, set normalizedEntity.allowed_extensions to
an empty array. Locate the normalizedEntity.allowed_extensions =
entity.allowed_extensions.split(","); line and replace it with this
normalized-and-filtered logic to avoid values like "" or " DOC".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0974360a-d264-4b65-b15d-cf377a433a8d

📥 Commits

Reviewing files that changed from the base of the PR and between e601202 and 3ce4a71.

📒 Files selected for processing (7)
  • src/actions/media-file-type-actions.js
  • src/i18n/en.json
  • src/pages/media_file_types/__tests__/media-file-type-list-page.test.js
  • src/pages/media_file_types/components/__tests__/media-file-type-dialog.test.js
  • src/pages/media_file_types/components/media-file-type-dialog.js
  • src/pages/media_file_types/media-file-type-list-page.js
  • src/reducers/media_file_types/media-file-type-list-reducer.js

Comment on lines +74 to +99
const handleRowEdit = (row) => {
getMediaFileType(row.id).then(() => setOpen(true));
};

const handleNew = () => {
resetMediaFileTypeForm();
setOpen(true);
};

const handleClose = () => {
resetMediaFileTypeForm();
setOpen(false);
};

const handleSave = (entity) => {
saveMediaFileType(entity)
.then(() =>
getMediaFileTypes(term, DEFAULT_CURRENT_PAGE, perPage, order, orderDir)
)
.then(() => setOpen(false));
};

const handleDelete = (mediaFileTypeId) => {
deleteMediaFileType(mediaFileTypeId).then(() =>
getMediaFileTypes(term, DEFAULT_CURRENT_PAGE, perPage, order, orderDir)
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Return/catch these async UI flows.

These handlers start request chains without a terminal catch, so failed fetch/save/delete calls can surface as unhandled promise rejections. handleSave also needs to return the promise so Formik can await the submit lifecycle.

Suggested fix
-  const handleRowEdit = (row) => {
-    getMediaFileType(row.id).then(() => setOpen(true));
-  };
+  const handleRowEdit = async (row) => {
+    try {
+      await getMediaFileType(row.id);
+      setOpen(true);
+    } catch {
+      // snackbarErrorHandler already surfaced the error
+    }
+  };
@@
-  const handleSave = (entity) => {
-    saveMediaFileType(entity)
-      .then(() =>
-        getMediaFileTypes(term, DEFAULT_CURRENT_PAGE, perPage, order, orderDir)
-      )
-      .then(() => setOpen(false));
-  };
+  const handleSave = async (entity) => {
+    try {
+      await saveMediaFileType(entity);
+      await getMediaFileTypes(
+        term,
+        DEFAULT_CURRENT_PAGE,
+        perPage,
+        order,
+        orderDir
+      );
+      setOpen(false);
+    } catch {
+      // snackbarErrorHandler already surfaced the error
+    }
+  };
@@
-  const handleDelete = (mediaFileTypeId) => {
-    deleteMediaFileType(mediaFileTypeId).then(() =>
-      getMediaFileTypes(term, DEFAULT_CURRENT_PAGE, perPage, order, orderDir)
-    );
-  };
+  const handleDelete = async (mediaFileTypeId) => {
+    try {
+      await deleteMediaFileType(mediaFileTypeId);
+      await getMediaFileTypes(
+        term,
+        DEFAULT_CURRENT_PAGE,
+        perPage,
+        order,
+        orderDir
+      );
+    } catch {
+      // snackbarErrorHandler already surfaced the error
+    }
+  };

Based on learnings, snackbarErrorHandler passed to request helpers already handles errors internally, and adding a catch after such requests is intentional to prevent unhandled promise rejections.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/media_file_types/media-file-type-list-page.js` around lines 74 -
99, The async UI handlers (handleRowEdit, handleSave, handleDelete and similar)
currently start promise chains without returning them or adding terminal
catches; update each to return the promise chain and attach a .catch that routes
errors to the existing snackbarErrorHandler (or otherwise handles the error) so
rejections are not unhandled; specifically: return getMediaFileType(...) from
handleRowEdit, return the reset/setOpen flows where applicable, make handleSave
return the
saveMediaFileType(...).then(getMediaFileTypes...).then(...).catch(snackbarErrorHandler)
so Formik can await it, and return
deleteMediaFileType(...).then(getMediaFileTypes...).catch(snackbarErrorHandler)
from handleDelete; keep using resetMediaFileTypeForm and setOpen as before but
ensure all chains are returned and terminally caught.

Comment thread src/pages/media_file_types/media-file-type-list-page.js Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/pages/media_file_types/media-file-type-list-page.js (1)

116-120: Consider defensive check for allowed_extensions.

The render assumes allowed_extensions is always an array. If the API ever returns null or undefined for this field, calling .join() will throw.

🛡️ Optional defensive fix
     {
       columnKey: "allowed_extensions",
       header: T.translate("media_file_type.allowed_extensions"),
-      render: (row) => row.allowed_extensions.join(", ")
+      render: (row) => (row.allowed_extensions || []).join(", ")
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/media_file_types/media-file-type-list-page.js` around lines 116 -
120, The render function for the column with columnKey "allowed_extensions"
assumes row.allowed_extensions is always an array, which will throw if it's
null/undefined; update the render in media-file-type-list-page (the render
callback) to defensively handle non-array values by checking
Array.isArray(row.allowed_extensions) (or using a fallback like an empty array
or a placeholder string) before calling join, so it safely returns a string when
allowed_extensions is missing or not an array.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/pages/media_file_types/media-file-type-list-page.js`:
- Around line 116-120: The render function for the column with columnKey
"allowed_extensions" assumes row.allowed_extensions is always an array, which
will throw if it's null/undefined; update the render in
media-file-type-list-page (the render callback) to defensively handle non-array
values by checking Array.isArray(row.allowed_extensions) (or using a fallback
like an empty array or a placeholder string) before calling join, so it safely
returns a string when allowed_extensions is missing or not an array.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6ab7c805-66c9-4bf9-a359-67053eecc659

📥 Commits

Reviewing files that changed from the base of the PR and between 3ce4a71 and 2d3dbd9.

📒 Files selected for processing (2)
  • src/pages/media_file_types/components/media-file-type-dialog.js
  • src/pages/media_file_types/media-file-type-list-page.js

@smarcet smarcet self-requested a review May 7, 2026 14:03
Comment thread src/actions/media-file-type-actions.js
Comment thread src/actions/media-file-type-actions.js
Comment thread src/pages/media_file_types/components/media-file-type-dialog.js
Comment thread src/pages/media_file_types/components/media-file-type-dialog.js Outdated
Comment thread src/pages/media_file_types/media-file-type-list-page.js
Comment thread src/pages/media_file_types/media-file-type-list-page.js Outdated
Comment thread src/reducers/media_file_types/media-file-type-list-reducer.js
Comment thread src/actions/media-file-type-actions.js
Comment thread src/actions/media-file-type-actions.js
Comment thread src/pages/media_file_types/components/media-file-type-dialog.js
Comment thread src/pages/media_file_types/components/media-file-type-dialog.js Outdated
Comment thread src/pages/media_file_types/media-file-type-list-page.js
Comment thread src/pages/media_file_types/media-file-type-list-page.js Outdated
Comment thread src/reducers/media_file_types/media-file-type-list-reducer.js
Copy link
Copy Markdown

@smarcet smarcet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tomrndom please review comments

Copy link
Copy Markdown

@smarcet smarcet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tomrndom please review

tomrndom added 3 commits May 19, 2026 16:34
Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
…fix typo

Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
Signed-off-by: Tomás Castillo <tcastilloboireau@gmail.com>
@tomrndom tomrndom force-pushed the fix/migrate-media-file-type-list branch from 2d3dbd9 to 57b1683 Compare May 19, 2026 19:35
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/layouts/media-file-type-layout.js (1)

30-32: ⚡ Quick win

Derive the fallback redirect from match.url.

Line 32 hardcodes the same base path that Line 31 already derives from the router. Reusing match.url keeps the fallback aligned if this layout is ever remounted under a different route prefix.

♻️ Suggested change
-      <Redirect to="/app/media-file-types" />
+      <Redirect to={match.url} />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/layouts/media-file-type-layout.js` around lines 30 - 32, The Redirect
uses a hardcoded "/app/media-file-types" fallback which can get out of sync;
change the Redirect to use the derived route prefix from match.url instead (i.e.
replace the hardcoded path in the <Redirect> with match.url or a join of
match.url + desired suffix) so the fallback stays aligned with the <Route exact
strict path={match.url} component={MediaFileTypeListPage}> and the surrounding
<Switch>/<Route>/<Redirect> logic.
src/pages/media_file_types/components/media-file-type-dialog.js (2)

88-88: 💤 Low value

Remove unnecessary size={12} prop on Grid2 container.

The Grid2 container at line 88 is a direct child of DialogContent, not nested within another grid. The size={12} prop has no effect in this context and can be removed for clarity.

🧹 Cleanup suggestion
-            <Grid2 container spacing={2} size={12} sx={{ p: 3 }}>
+            <Grid2 container spacing={2} sx={{ p: 3 }}>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/media_file_types/components/media-file-type-dialog.js` at line 88,
In the MediaFileTypeDialog component remove the unused size={12} prop from the
Grid2 container (the element created with <Grid2 container ...>) inside
DialogContent; simply delete the size={12} attribute so the container uses its
container behavior only and no redundant column sizing remains.

34-36: ⚡ Quick win

Consider adding validation for allowed_extensions.

The allowed_extensions field is converted from an array to a CSV string but has no validation. Users can submit an empty string or malformed input. Consider adding a Yup validator to ensure at least one extension is provided and that entries are non-empty after trimming.

✅ Example validation
     validationSchema: yup.object().shape({
-      name: requiredStringValidation()
+      name: requiredStringValidation(),
+      allowed_extensions: yup
+        .string()
+        .required('At least one extension is required')
+        .test('has-valid-extensions', 'Extensions must be comma-separated non-empty values', (value) => {
+          if (!value) return false;
+          const extensions = value.split(',').map(e => e.trim()).filter(e => e.length > 0);
+          return extensions.length > 0;
+        })
     }),

Also applies to: 121-130

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/media_file_types/components/media-file-type-dialog.js` around lines
34 - 36, The allowed_extensions value is converted to CSV but lacks validation;
update the form validation schema (the Yup schema used in
media-file-type-dialog.js) to add a rule for allowed_extensions that splits the
CSV by commas, trims each entry, filters out empty strings, and requires the
resulting array to have length > 0 and all entries match a simple extension
pattern (e.g., non-empty alphanumeric/underscore/dot characters); ensure the
same validation is applied where initialEntity?.allowed_extensions is handled
(the CSV conversion at allowed_extensions:
Array.isArray(initialEntity?.allowed_extensions) ... and the corresponding form
submit/parse logic around lines ~121-130) so malformed or empty entries are
rejected with a clear error message.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/media_file_types/components/media-file-type-dialog.js`:
- Line 27: The component is using the isSaving prop but it isn't declared in
PropTypes; update the MediaFileTypeDialog component (media-file-type-dialog.js)
to add isSaving: PropTypes.bool (or PropTypes.oneOfType([PropTypes.bool,
PropTypes.any]) if other types used) to the component's PropTypes declaration
and add a sensible default in defaultProps (e.g., isSaving: false) so prop
validation covers the prop referenced throughout the component (also update any
exported or wrapped component PropTypes if there are multiple declarations
around the component).
- Line 62: The dialog's onClose (onClose={handleClose}) allows backdrop clicks
to close/reset while isSaving is true; update the Dialog's onClose prop to
ignore backdrop clicks during saves by using the onClose signature (e, reason)
and returning early when reason === 'backdropClick' && isSaving, otherwise call
handleClose; reference the existing symbols handleClose and isSaving in
media-file-type-dialog.js.

---

Nitpick comments:
In `@src/layouts/media-file-type-layout.js`:
- Around line 30-32: The Redirect uses a hardcoded "/app/media-file-types"
fallback which can get out of sync; change the Redirect to use the derived route
prefix from match.url instead (i.e. replace the hardcoded path in the <Redirect>
with match.url or a join of match.url + desired suffix) so the fallback stays
aligned with the <Route exact strict path={match.url}
component={MediaFileTypeListPage}> and the surrounding
<Switch>/<Route>/<Redirect> logic.

In `@src/pages/media_file_types/components/media-file-type-dialog.js`:
- Line 88: In the MediaFileTypeDialog component remove the unused size={12} prop
from the Grid2 container (the element created with <Grid2 container ...>) inside
DialogContent; simply delete the size={12} attribute so the container uses its
container behavior only and no redundant column sizing remains.
- Around line 34-36: The allowed_extensions value is converted to CSV but lacks
validation; update the form validation schema (the Yup schema used in
media-file-type-dialog.js) to add a rule for allowed_extensions that splits the
CSV by commas, trims each entry, filters out empty strings, and requires the
resulting array to have length > 0 and all entries match a simple extension
pattern (e.g., non-empty alphanumeric/underscore/dot characters); ensure the
same validation is applied where initialEntity?.allowed_extensions is handled
(the CSV conversion at allowed_extensions:
Array.isArray(initialEntity?.allowed_extensions) ... and the corresponding form
submit/parse logic around lines ~121-130) so malformed or empty entries are
rejected with a clear error message.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7c35f84e-a9fa-4190-a5b8-ea8785b8d1ef

📥 Commits

Reviewing files that changed from the base of the PR and between 2d3dbd9 and 57b1683.

📒 Files selected for processing (8)
  • src/actions/media-file-type-actions.js
  • src/i18n/en.json
  • src/layouts/media-file-type-layout.js
  • src/pages/media_file_types/__tests__/media-file-type-list-page.test.js
  • src/pages/media_file_types/components/__tests__/media-file-type-dialog.test.js
  • src/pages/media_file_types/components/media-file-type-dialog.js
  • src/pages/media_file_types/edit-media-file-type-page.js
  • src/pages/media_file_types/media-file-type-list-page.js
💤 Files with no reviewable changes (1)
  • src/pages/media_file_types/edit-media-file-type-page.js
✅ Files skipped from review due to trivial changes (1)
  • src/i18n/en.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/pages/media_file_types/components/tests/media-file-type-dialog.test.js
  • src/pages/media_file_types/media-file-type-list-page.js
  • src/pages/media_file_types/tests/media-file-type-list-page.test.js
  • src/actions/media-file-type-actions.js

entity: initialEntity,
onClose,
onSave,
isSaving = false
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add isSaving to PropTypes.

The isSaving prop is used throughout the component but is not declared in PropTypes. This creates a maintenance risk and bypasses prop validation.

📝 Proposed fix
 MediaFileTypeDialog.propTypes = {
   entity: PropTypes.object,
   onClose: PropTypes.func.isRequired,
-  onSave: PropTypes.func.isRequired
+  onSave: PropTypes.func.isRequired,
+  isSaving: PropTypes.bool
 };

Also applies to: 151-155

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/media_file_types/components/media-file-type-dialog.js` at line 27,
The component is using the isSaving prop but it isn't declared in PropTypes;
update the MediaFileTypeDialog component (media-file-type-dialog.js) to add
isSaving: PropTypes.bool (or PropTypes.oneOfType([PropTypes.bool,
PropTypes.any]) if other types used) to the component's PropTypes declaration
and add a sensible default in defaultProps (e.g., isSaving: false) so prop
validation covers the prop referenced throughout the component (also update any
exported or wrapped component PropTypes if there are multiple declarations
around the component).

return (
<Dialog
open
onClose={handleClose}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disable backdrop click during save to prevent race conditions.

The dialog's onClose handler is called on backdrop click even when isSaving is true. A user clicking outside the dialog mid-save will reset the form and close it, potentially causing concurrent saves or data loss if they reopen and save again.

🔒 Proposed fix
     <Dialog
       open
-      onClose={handleClose}
+      onClose={(event, reason) => {
+        if (reason === 'backdropClick' && isSaving) return;
+        handleClose();
+      }}
       maxWidth="sm"
       fullWidth
       disableEscapeKeyDown={isSaving}
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onClose={handleClose}
<Dialog
open
onClose={(event, reason) => {
if (reason === 'backdropClick' && isSaving) return;
handleClose();
}}
maxWidth="sm"
fullWidth
disableEscapeKeyDown={isSaving}
>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/media_file_types/components/media-file-type-dialog.js` at line 62,
The dialog's onClose (onClose={handleClose}) allows backdrop clicks to
close/reset while isSaving is true; update the Dialog's onClose prop to ignore
backdrop clicks during saves by using the onClose signature (e, reason) and
returning early when reason === 'backdropClick' && isSaving, otherwise call
handleClose; reference the existing symbols handleClose and isSaving in
media-file-type-dialog.js.

@tomrndom tomrndom requested a review from smarcet May 19, 2026 20:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants