Skip to content

feat: delete confirm modal#3024

Closed
jesperhodge wants to merge 3 commits intoopenedx:masterfrom
jesperhodge:feat--delete-modal
Closed

feat: delete confirm modal#3024
jesperhodge wants to merge 3 commits intoopenedx:masterfrom
jesperhodge:feat--delete-modal

Conversation

@jesperhodge
Copy link
Copy Markdown
Contributor

@jesperhodge jesperhodge commented Apr 24, 2026

Description

This is part of openedx/modular-learning#260 - a split-out so that it's smaller PRs to review.

The intention is to have a type confirm modal for deletions, but keep the actual deletion logic separate.

Important

The test button needs to be deleted before merging this.

Testing instructions

  • Go to authoring/home -> taxonomies -> click on a taxonomy -> click on "Test Delete Modal" button

Use of AI

  • AI helped write the tests
  • AI split apart the code from the delete functionality to have two independent PRs

Best Practices Checklist

We're trying to move away from some deprecated patterns in this codebase. Please
check if your PR meets these recommendations before asking for a review:

  • Any new files are using TypeScript (.ts, .tsx).
  • Avoid propTypes and defaultProps in any new or modified code.
  • Tests should use the helpers in src/testUtils.tsx (specifically initializeMocks)
  • Do not add new fields to the Redux state/store. Use React Context to share state among multiple components.
  • Use React Query to load data from REST APIs. See any apiHooks.ts in this repo for examples.
  • All new i18n messages in messages.ts files have a description for translators to use.
  • Avoid using ../ in import paths. To import from parent folders, use @src, e.g. import { initializeMocks } from '@src/testUtils'; instead of from '../../../../testUtils'

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Apr 24, 2026
@openedx-webhooks
Copy link
Copy Markdown

openedx-webhooks commented Apr 24, 2026

Thanks for the pull request, @jesperhodge!

This repository is currently maintained by @bradenmacdonald.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@jesperhodge jesperhodge marked this pull request as ready for review April 24, 2026 00:44
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 24, 2026

Codecov Report

❌ Patch coverage is 98.87640% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 95.47%. Comparing base (57b770b) to head (e7228cb).
⚠️ Report is 14 commits behind head on master.

Files with missing lines Patch % Lines
src/taxonomy/tag-list/TagListTable.tsx 92.85% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           master    #3024    +/-   ##
========================================
  Coverage   95.47%   95.47%            
========================================
  Files        1383     1384     +1     
  Lines       32645    32652     +7     
  Branches     7472     7246   -226     
========================================
+ Hits        31168    31176     +8     
- Misses       1408     1420    +12     
+ Partials       69       56    -13     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

This was referenced Apr 24, 2026
Copy link
Copy Markdown
Contributor

@mgwozdz-unicon mgwozdz-unicon left a comment

Choose a reason for hiding this comment

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

I tested this locally and I believe it works as intended. However, please see comments regarding PR split and recommended code comments.

row.original as unknown as TagListRowData
);

export const getTagWithDescendantsCount = (rowData: TreeRowData): number => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it would be good to add a comment explaining in more detail how the Descendant count is being calculated as I could see this potentially being confusing to someone who's picking this code up for the first time.

@@ -0,0 +1,33 @@
import { getTagWithDescendantsCount } from './utils';

describe('getTagsWithDescendantCount', () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it would be good to add a comment explaining in more detail how the Descendant count is being calculated as I could see this potentially being confusing to someone who's picking this code up for the first time.

/>
<>
<div className="d-flex justify-content-end mb-3">
{/* TODO: remove after testing */}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If the Open edX Core Contributor reviewers disagree with me here, then I defer to their preference. However, I don't think this PR is safely functionally separate from #3025 . Personally, I don't consider it okay to merge code with testing artifacts visible in the frontend because I believe that a merged PR should be ready for prod. Either this PR should have been in the Draft state until the testing artifact is removed or these 2 PRs should be combined back together. Additionally, I don't like submitting PRs dependent on each other that don't have to be. As much as possible, each PR should be able to function in production on its own with no dependencies, and to me, those things are a higher priority than shrinking PR size.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I agree with you, though in this case I think the simplest approach is to review and test this PR with the test button in place and then delete it before merging the PR. That can be done by adding the button with a separate commit that uses the temp: prefix and keeping the PR in a draft state until that's removed.

By the way, I wish we had a storybook-like "guide to available UX patterns" page for developers in the app somewhere, which would be a another way of solving this problem. I did this on a past project and I really liked the approach.

Alternately, this could be incorporated into the other PR and just try to use commits to keep things separate for reviewers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That makes sense. I agree that the simplest approach is to revert the PR to draft or treat it as if it's in draft until the test button is removed.

@brian-smith-tcril brian-smith-tcril added the create-sandbox open-craft-grove should create a sandbox environment from this PR label Apr 27, 2026
Copy link
Copy Markdown
Contributor

@brian-smith-tcril brian-smith-tcril left a comment

Choose a reason for hiding this comment

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

Overall I like the direction this is heading, but it's not ready to merge.

I started by reading through the code and left a few comments. I then created a sandbox and I found a few issues when testing.

import React from 'react';
import userEvent from '@testing-library/user-event';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { fireEvent, render, screen } from '@testing-library/react';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's generally best practice to use userEvent instead of fireEvent. See https://testing-library.com/docs/user-event/intro/#differences-from-fireevent

cancelLabel: string;
X: string;
// any additional context that the caller wants to pass to the onConfirm callback; not a React context.
context?: Record<string, any> | null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The fact that this needs a descriptive comment makes me think we could probably use a better name here, maybe something like callbackParams?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I decided to go with confirmPayload since that's where this context is getting passed.

Comment on lines +112 to +119
<ModalDialog.Footer>
<Button variant="tertiary" onClick={handleCancel}>
{cancelLabel}
</Button>
<Button onClick={handleConfirm} disabled={!confirmedByTyping} variant="danger">
{confirmLabel}
</Button>
</ModalDialog.Footer>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The spacing in here is off, the examples in https://paragon-openedx.netlify.app/components/modal/modal-dialog/ have the footer buttons in an ActionRow, I think that'll likely fix the spacing.

Image

Comment on lines +95 to +104
const messageText = intl.formatMessage(messages.typeToConfirmInstruction, { X });
const parts = messageText.split(X);
return (
<>
{parts[0]}
<strong>{X}</strong>
{parts[1]}
</>
);
})()}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there a time when we'd use the "Type X to confirm" without <strong>? The "with rich text formatting" example in the formatjs api docs https://formatjs.github.io/docs/react-intl/api/ has

const messages = defineMessages({
  greeting: {
    id: 'app.greeting',
    defaultMessage: 'Hello, <bold>{name}</bold>!',
    description: 'Greeting to welcome the user to the app',
  },
})

intl.formatMessage(messages.greeting, {name: 'Eric', bold: str => <b>{str}</b>})

and in the live code editor there I tested

const messages = defineMessages({
  greeting: {
    id: 'app.greeting',
    defaultMessage: 'Hello, <strong>{name}</strong>!',
    description: 'Greeting to welcome the user to the app',
  },
})

intl.formatMessage(messages.greeting, {name: 'Eric', strong: str => <strong>{str}</strong>})

and it worked

Comment on lines +38 to +40
if (e.key === 'Enter') {
onConfirm(context);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This isn't closing the modal.

Screencast.From.2026-04-27.14-52-35.mp4

Copy link
Copy Markdown
Contributor

@brian-smith-tcril brian-smith-tcril Apr 27, 2026

Choose a reason for hiding this comment

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

I guess the other question is, "do we want this functionality?" Should hitting enter while in the input box count as confirmation? I'd think needing to tab over to the "Delete Tags" button would be reasonable (and less likely to result in unexpected behavior)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good point. Since the acceptance criteria do not require Enter from the text input to confirm, I’m going to remove that shortcut and require users to explicitly activate the enabled Delete Tags button. Keyboard users can still tab to the button and press Enter, and this keeps the destructive action a little more intentional.

mgwozdz-unicon added a commit to mgwozdz-unicon/frontend-app-authoring that referenced this pull request Apr 28, 2026
@mgwozdz-unicon mgwozdz-unicon mentioned this pull request Apr 28, 2026
7 tasks
@mphilbrick211 mphilbrick211 moved this from Needs Triage to In Eng Review in Contributions Apr 29, 2026
@ormsbee
Copy link
Copy Markdown
Contributor

ormsbee commented Apr 29, 2026

This is superseded by #3033

@ormsbee ormsbee closed this Apr 29, 2026
@github-project-automation github-project-automation Bot moved this from In Eng Review to Done in Contributions Apr 29, 2026
@brian-smith-tcril brian-smith-tcril removed the create-sandbox open-craft-grove should create a sandbox environment from this PR label Apr 29, 2026
brian-smith-tcril pushed a commit that referenced this pull request Apr 29, 2026
* feat: delete confirm modal

* docs: add todo to remove code

* fix: lint

* fix: address comments on PR #3024

Co-authored-by: Copilot <[email protected]>

* feat: Remove testing artifacts

* fix: Remove unused variable

---------

Co-authored-by: Jesper Hodge <[email protected]>
Co-authored-by: Copilot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

open-source-contribution PR author is not from Axim or 2U

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

7 participants