Skip to content

Refactor: unify delete and restore issue actions and move conditional logic into typescript file#1360

Merged
wx-03 merged 6 commits intoCATcher-org:masterfrom
TobyCyan:fix-issue-1315
Jul 9, 2025
Merged

Refactor: unify delete and restore issue actions and move conditional logic into typescript file#1360
wx-03 merged 6 commits intoCATcher-org:masterfrom
TobyCyan:fix-issue-1315

Conversation

@TobyCyan
Copy link
Copy Markdown
Contributor

@TobyCyan TobyCyan commented Jun 30, 2025

Summary:

Fixes #1315

Changes Made:

  • Moved long boolean statements from the html to the typescript file for better readability.
  • Combined the delete and restore issue actions into a single method, alongside with one handler helper method that is toggled by passing in a boolean argument.
  • Combined the 2 separate lists issuesPendingDeletion and issuesPendingRestore into a single issuesPendingAction.

Proposed Commit Message:

Refactor issue actions and conditions for clarity and maintainability

The deleteIssue and undeleteIssue methods share highly similar logic
that performs the same actions in opposite directions.

This causes code duplication and makes future maintenance more 
error-prone.

Let's,
* extract the common logic into a reusable function to eliminate
duplication and improve clarity.
* merge the two separate state-tracking lists — 
issuesPendingDeletion and issuesPendingRestore into a 
single list issuesPendingAction.
* move complex conditional logic in issue-tables.component.html 
into issue-tables.component.ts.

This makes the template easier to read, improves maintainability,
and reduce duplicated code for the same actions in reverse.

@damithc
Copy link
Copy Markdown
Contributor

damithc commented Jul 1, 2025

Tagging @NorbertLoh @HollaG @wx-03 @IzN432 in case any of you can help with the PR ...

@damithc damithc requested review from Copilot and wx-03 July 7, 2025 04:41
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the issue actions by moving conditional logic out of the template and unifying delete/restore flows into a single handler, while consolidating pending-action tracking into one structure.

  • Moved complex boolean expressions from the HTML template into dedicated TypeScript methods.
  • Combined delete and restore logic into deleteOrRestoreIssue with a boolean toggle.
  • Replaced two pending-action maps with a single issuesPendingAction map.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/app/shared/issue-tables/issue-tables.component.ts Unified delete/restore methods, moved template logic, consolidated pending flags
src/app/shared/issue-tables/issue-tables.component.html Updated action buttons to use new helper methods
Comments suppressed due to low confidence (1)

src/app/shared/issue-tables/issue-tables.component.ts:160

  • [nitpick] Add JSDoc comments for this method (and other new helper methods) to describe parameters, side effects, and intended behavior, improving maintainability.
  deleteOrRestoreIssue(isDeleteAction: boolean, id: number, event: Event, actionUndoable: boolean = true) {

*ngIf="permissions.isIssueDeletable() && !issuesPendingDeletion[issue.id] && this.isActionVisible(action_buttons.DELETE_ISSUE)"
(click)="deleteIssue(issue.id, $event); $event.stopPropagation()"
*ngIf="isActionPerformAllowed(true, issue.id)"
(click)="deleteOrRestoreIssue(true, issue.id, $event); $event.stopPropagation()"
Copy link

Copilot AI Jul 7, 2025

Choose a reason for hiding this comment

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

There’s a duplicate stopPropagation() call here and in the component method. Remove the inline $event.stopPropagation() in the template since deleteOrRestoreIssue already handles it.

Suggested change
(click)="deleteOrRestoreIssue(true, issue.id, $event); $event.stopPropagation()"
(click)="deleteOrRestoreIssue(true, issue.id, $event)"

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@wx-03 wx-03 Jul 7, 2025

Choose a reason for hiding this comment

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

There’s a duplicate stopPropagation() call here and in the component method. Remove the inline $event.stopPropagation() in the template since deleteOrRestoreIssue already handles it.

Agree with this

(actionedIssue) => this.handleIssueActionPerformedSuccess(isDeleteAction, id, event, actionUndoable),
(error) => this.errorHandlingService.handleError(error)
);
event.stopPropagation();
Copy link

Copilot AI Jul 7, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider handling event propagation in one place only—either in the template or inside this method—to avoid redundant calls and improve clarity.

Suggested change
event.stopPropagation();
// Removed event.stopPropagation() to handle event propagation in the template.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@wx-03 wx-03 Jul 7, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider handling event propagation in one place only—either in the template or inside this method—to avoid redundant calls and improve clarity.

Maybe the event.stopPropagation() can be removed from the template and kept here instead.

)
.subscribe(
(removedIssue) => this.handleIssueDeletionSuccess(id, event, actionUndoable),
(actionedIssue) => this.handleIssueActionPerformedSuccess(isDeleteAction, id, event, actionUndoable),
Copy link

Copilot AI Jul 7, 2025

Choose a reason for hiding this comment

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

The actionedIssue callback parameter is never used. You can simplify this to () => ... to remove the unused parameter and make the code clearer.

Suggested change
(actionedIssue) => this.handleIssueActionPerformedSuccess(isDeleteAction, id, event, actionUndoable),
() => this.handleIssueActionPerformedSuccess(isDeleteAction, id, event, actionUndoable),

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@wx-03 wx-03 Jul 7, 2025

Choose a reason for hiding this comment

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

The actionedIssue callback parameter is never used. You can simplify this to () => ... to remove the unused parameter and make the code clearer.

Agree with this too

Comment on lines +160 to +168
deleteOrRestoreIssue(isDeleteAction: boolean, id: number, event: Event, actionUndoable: boolean = true) {
const deletingKeyword = 'Deleting';
const undeletingKeyword = 'Undeleting';
this.logger.info(`IssueTablesComponent: ${isDeleteAction ? deletingKeyword : undeletingKeyword} Issue ${id}`);

deleteIssue(id: number, event: Event, actionUndoable: boolean = true) {
this.logger.info(`IssueTablesComponent: Deleting Issue ${id}`);
this.issuesPendingAction = { ...this.issuesPendingAction, [id]: true };

this.issuesPendingDeletion = { ...this.issuesPendingDeletion, [id]: true };
this.issueService
.deleteIssue(id)
let observableActionedIssue: Observable<Issue>;
if (isDeleteAction) {
Copy link

Copilot AI Jul 7, 2025

Choose a reason for hiding this comment

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

[nitpick] Using a boolean flag to toggle delete vs. restore can be error-prone and less readable. Consider using an enum or separate named methods to make the intent explicit.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@wx-03 wx-03 Jul 7, 2025

Choose a reason for hiding this comment

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

[nitpick] Using a boolean flag to toggle delete vs. restore can be error-prone and less readable. Consider using an enum or separate named methods to make the intent explicit.

While an enum could make the intent more explicit, I think a boolean works well here given that the function is only used in the HTML for delete/restore actions. Using a boolean also makes toggling for undo more straightforward.

Copy link
Copy Markdown
Contributor

@wx-03 wx-03 left a comment

Choose a reason for hiding this comment

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

Good job on refactoring all the boolean statements and combining the deletion and restoration of issues! Overall lgtm, left some comments on which of copilot's suggestions are worth keeping

Comment on lines +160 to +168
deleteOrRestoreIssue(isDeleteAction: boolean, id: number, event: Event, actionUndoable: boolean = true) {
const deletingKeyword = 'Deleting';
const undeletingKeyword = 'Undeleting';
this.logger.info(`IssueTablesComponent: ${isDeleteAction ? deletingKeyword : undeletingKeyword} Issue ${id}`);

deleteIssue(id: number, event: Event, actionUndoable: boolean = true) {
this.logger.info(`IssueTablesComponent: Deleting Issue ${id}`);
this.issuesPendingAction = { ...this.issuesPendingAction, [id]: true };

this.issuesPendingDeletion = { ...this.issuesPendingDeletion, [id]: true };
this.issueService
.deleteIssue(id)
let observableActionedIssue: Observable<Issue>;
if (isDeleteAction) {
Copy link
Copy Markdown
Contributor

@wx-03 wx-03 Jul 7, 2025

Choose a reason for hiding this comment

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

[nitpick] Using a boolean flag to toggle delete vs. restore can be error-prone and less readable. Consider using an enum or separate named methods to make the intent explicit.

While an enum could make the intent more explicit, I think a boolean works well here given that the function is only used in the HTML for delete/restore actions. Using a boolean also makes toggling for undo more straightforward.

*ngIf="permissions.isIssueDeletable() && !issuesPendingDeletion[issue.id] && this.isActionVisible(action_buttons.DELETE_ISSUE)"
(click)="deleteIssue(issue.id, $event); $event.stopPropagation()"
*ngIf="isActionPerformAllowed(true, issue.id)"
(click)="deleteOrRestoreIssue(true, issue.id, $event); $event.stopPropagation()"
Copy link
Copy Markdown
Contributor

@wx-03 wx-03 Jul 7, 2025

Choose a reason for hiding this comment

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

There’s a duplicate stopPropagation() call here and in the component method. Remove the inline $event.stopPropagation() in the template since deleteOrRestoreIssue already handles it.

Agree with this

)
.subscribe(
(removedIssue) => this.handleIssueDeletionSuccess(id, event, actionUndoable),
(actionedIssue) => this.handleIssueActionPerformedSuccess(isDeleteAction, id, event, actionUndoable),
Copy link
Copy Markdown
Contributor

@wx-03 wx-03 Jul 7, 2025

Choose a reason for hiding this comment

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

The actionedIssue callback parameter is never used. You can simplify this to () => ... to remove the unused parameter and make the code clearer.

Agree with this too

(actionedIssue) => this.handleIssueActionPerformedSuccess(isDeleteAction, id, event, actionUndoable),
(error) => this.errorHandlingService.handleError(error)
);
event.stopPropagation();
Copy link
Copy Markdown
Contributor

@wx-03 wx-03 Jul 7, 2025

Choose a reason for hiding this comment

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

[nitpick] Consider handling event propagation in one place only—either in the template or inside this method—to avoid redundant calls and improve clarity.

Maybe the event.stopPropagation() can be removed from the template and kept here instead.

@TobyCyan TobyCyan requested a review from wx-03 July 8, 2025 02:12
Copy link
Copy Markdown
Contributor

@wx-03 wx-03 left a comment

Choose a reason for hiding this comment

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

Sorry I missed this in the previous review, but could you update the commit message body to follow the Git conventions mentioned here? Everything else looks good. I'll merge once the commit message has been edited!

@TobyCyan
Copy link
Copy Markdown
Contributor Author

TobyCyan commented Jul 9, 2025

Sorry I missed this in the previous review, but could you update the commit message body to follow the Git conventions mentioned here? Everything else looks good. I'll merge once the commit message has been edited!

hi, apologies for the poorly-craft commit message body. I've updated it to follow the convention as much as I could, could you please review it? Thanks!

@wx-03
Copy link
Copy Markdown
Contributor

wx-03 commented Jul 9, 2025

Sorry I missed this in the previous review, but could you update the commit message body to follow the Git conventions mentioned here? Everything else looks good. I'll merge once the commit message has been edited!

hi, apologies for the poorly-craft commit message body. I've updated it to follow the convention as much as I could, could you please review it? Thanks!

LGTM!

@wx-03 wx-03 merged commit 7ced8ae into CATcher-org:master Jul 9, 2025
5 checks passed
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.

Refactor IssueTablesComponent

4 participants