Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add emptyOrgRecycleBin to clean up space used by large amounts of records in the recycle bin #492

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions src/plugins/empty-org-recycle-bin/disable.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "../schema.json",
"settings": {
"emptyOrgRecycleBin": {
"enabled": false
}
}
}
8 changes: 8 additions & 0 deletions src/plugins/empty-org-recycle-bin/enable.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
Copy link
Owner

Choose a reason for hiding this comment

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

When you start developing the tests,

  • enable.json could be renamed to empty-org-recycle-bin.json
  • disable.json could probably be removed

"$schema": "../schema.json",
"settings": {
"emptyOrgRecycleBin": {
"enabled": true
}
}
}
42 changes: 42 additions & 0 deletions src/plugins/empty-org-recycle-bin/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { BrowserforcePlugin } from '../../plugin';

const DELETE_EVENT_OBJECT = 'DeleteEvent';
const LIST_VIEW_ALL_DELETE_EVENTS = 'AllDeleteEvents';
const DELETE_EVENT_EMPTY_ALL_ACTION = 'DeleteEventEmptyAllAction';

const PATHS = {
BASE: 'lightning/o/DeleteEvent/home'
};

const SELECTORS = {
EMPTY_BUTTON: '.modal-container .modal-footer button.uiButton:last-of-type'
};

export class EmptyOrgRecycleBin extends BrowserforcePlugin {
public async retrieve(definition?: Config): Promise<Config> {
return { enabled: false };
}

public async apply(config: Config): Promise<void> {
const deleteEventEmptyAllButtonSelector = `a.forceActionLink[title="${await this.determineDeleteEventEmptyAllActionLabel()}"]`;
Copy link
Owner

Choose a reason for hiding this comment

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

Given that we assume the "Empty" button in the dialog is the last button,
can we maybe also just assume the "Empty Org Recycle Bin" is the last item of the forceActionsContainer?
As far as I can see, the button is there regardless if there are items in the Recycle Bin or not and I'm able to click it even if the Recycle Bin is empty.

Suggested change
const deleteEventEmptyAllButtonSelector = `a.forceActionLink[title="${await this.determineDeleteEventEmptyAllActionLabel()}"]`;
const deleteEventEmptyAllButtonSelector = `ul.forceActionsContainer li:last-of-type a`;

In that case we could go without using the UI API for simplicity and performance.
But it's great to see a use case of this API. 👏


const page = await this.browserforce.openPage(PATHS.BASE);
await page.waitForSelector(deleteEventEmptyAllButtonSelector);
await page.click(deleteEventEmptyAllButtonSelector);
await page.waitForSelector(SELECTORS.EMPTY_BUTTON);
await page.click(SELECTORS.EMPTY_BUTTON);
Copy link
Owner

Choose a reason for hiding this comment

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

In my tests, the recycle bin was not emptied.

Maybe we need to wait for a successful response from the server like this:

Suggested change
await page.click(SELECTORS.EMPTY_BUTTON);
await Promise.all([
page.waitForResponse(
response =>
response
.url()
.includes(
'RecycleBinActions.emptyOrgRecycleBin=1'
) && response.status() === 200
),
page.click(SELECTORS.EMPTY_BUTTON)
]);

}

private async determineDeleteEventEmptyAllActionLabel(): Promise<string> {
const conn = this.org.getConnection();
const deleteEventListViewsUrl = `${conn.instanceUrl}/services/data/v${conn.getApiVersion()}/ui-api/list-ui/${DELETE_EVENT_OBJECT}`;
const deleteEventListViewsResponse = await conn.request(deleteEventListViewsUrl);
const allDeleteEventsListView = deleteEventListViewsResponse['lists'].filter((value) => value.apiName == LIST_VIEW_ALL_DELETE_EVENTS)[0];
const allDeleteEventsListViewId = allDeleteEventsListView['id'];
const allDeleteEventsListViewActionsUrl = `${conn.instanceUrl}/services/data/v${conn.getApiVersion()}/ui-api/actions/list-view/${allDeleteEventsListViewId}`;
const allDeleteEventsListViewActionsResponse = await conn.request(allDeleteEventsListViewActionsUrl);
const deleteEventEmptyAllEventsAction = allDeleteEventsListViewActionsResponse['actions'][allDeleteEventsListViewId]['actions'].filter((value) => value.apiName == DELETE_EVENT_EMPTY_ALL_ACTION)[0];

return deleteEventEmptyAllEventsAction.label;
}
}
13 changes: 13 additions & 0 deletions src/plugins/empty-org-recycle-bin/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
Copy link
Owner

Choose a reason for hiding this comment

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

How about naming the directory simply recycle-bin?

In this case, the schema could look like this:

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "$id": "https://github.com/amtrack/sfdx-browserforce-plugin/src/plugins/recycle-bin/schema.json",
  "title": "RecycleBin Settings",
  "type": "object",
  "properties": {
    "emptyOrgRecycleBin": {
      "title": "Empty Org Recycle Bin",
      "description": "All items are permanently deleted. You can't undo this action.",
      "type": "boolean"
    }
  }
}

and a config could look like this:

{
  "$schema": "../schema.json",
  "settings": {
    "recycleBin": {
      "emptyOrgRecycleBin": true
    }
  }
}

"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://github.com/amtrack/sfdx-browserforce-plugin/src/plugins/empty-org-recycle-bin/schema.json",
"title": "EmptyOrgRecycleBin Settings",
"type": "object",
"properties": {
"enabled": {
"title": "Enable EmptyOrgRecycleBin",
"description": "The description you want to be displayed as toolip when the user is editing the configuration",
"type": "boolean"
}
}
}
3 changes: 3 additions & 0 deletions src/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import { Security as security } from './security';

import { RelateContactToMultipleAccounts as relateContactToMultipleAccounts } from './relate-contact-to-multiple-accounts';

import { EmptyOrgRecycleBin as emptyOrgRecycleBin } from './empty-org-recycle-bin';

export {
emptyOrgRecycleBin,
relateContactToMultipleAccounts,
activitySettings,
communities,
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"properties": {
"settings": {
"properties": {
"emptyOrgRecycleBin": {
"$ref": "./empty-org-recycle-bin/schema.json"
},
"relateContactToMultipleAccounts": {
"$ref": "./relate-contact-to-multiple-accounts/schema.json"
},
Expand Down