Skip to content

Commit

Permalink
fix: avoid multiple API calls to load the inbox when datasets/attachm…
Browse files Browse the repository at this point in the history
…ents are deleted (#1839)

add the bulk delete API endpoint for attachments
error message is logged into the Rails log

Co-authored-by: Tasnim Mehzabin <[email protected]>
  • Loading branch information
TasnimMehzabin and Tasnim Mehzabin authored Mar 28, 2024
1 parent 38b0d84 commit 84c8806
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 4 deletions.
21 changes: 21 additions & 0 deletions app/api/chemotion/attachment_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ def remove_duplicated(att)

resource :attachments do
before do
next if request.path.end_with?('bulk_delete') && request.request_method == 'DELETE'

@attachment = Attachment.find_by(id: params[:attachment_id])

@attachment = Attachment.find_by(identifier: params[:identifier]) if @attachment.nil? && params[:identifier]
Expand Down Expand Up @@ -112,6 +114,25 @@ def remove_duplicated(att)
end
end

desc 'Bulk Delete Attachments'
delete 'bulk_delete' do
ids = params[:ids]
attachments = Attachment.where(id: ids)

unpermitted_attachments = attachments.reject { |attachment| writable?(attachment) }

if unpermitted_attachments.any?
error!('401 Unauthorized', 401)
else
deleted_attachments = attachments.destroy_all
end

render json: { deleted_attachments: deleted_attachments }, status: :ok
rescue StandardError => e
render json: { error: e.message }, status: :unprocessable_entity
Rails.logger.error("Error deleting attachments: #{e.message}")
end

desc 'Delete Attachment'
delete ':attachment_id' do
present Usecases::Attachments::Delete.execute!(@attachment),
Expand Down
10 changes: 8 additions & 2 deletions app/packs/src/apps/mydb/inbox/DeviceBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ export default class DeviceBox extends React.Component {
const currentItemsCount = device_box.children.length;
const itemsDeleted = checkedDeviceIds.length;

const attachmentIdsToDelete = [];

checkedDeviceIds.forEach((checkedDeviceId) => {
const datasetToDelete = device_box.children.find((dataset) => dataset.id === checkedDeviceId);
if (datasetToDelete) {
Expand All @@ -199,11 +201,15 @@ export default class DeviceBox extends React.Component {
device_box.children.forEach((dataset) => {
const attachmentToDelete = dataset.attachments.find((attachment) => attachment.id === checkedId);
if (attachmentToDelete) {
InboxActions.deleteAttachment(attachmentToDelete, false);
attachmentIdsToDelete.push(checkedId);
}
});
});

if (attachmentIdsToDelete.length > 0) {
InboxActions.bulkDeleteAttachments(attachmentIdsToDelete, false);
}

const params = {
checkedDeviceIds: [],
checkedIds: [],
Expand Down Expand Up @@ -378,4 +384,4 @@ DeviceBox.propTypes = {
DeviceBox.defaultProps = {
largerInbox: false,
deviceBoxVisible: false,
};
};
21 changes: 20 additions & 1 deletion app/packs/src/fetchers/AttachmentFetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,25 @@ export default class AttachmentFetcher {
return promise;
}

static bulkDeleteAttachments(attachmentIdsToDelete) {
const promise = fetch('/api/v1/attachments/bulk_delete', {
credentials: 'same-origin',
method: 'DELETE',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ ids: attachmentIdsToDelete }),
})
.then((response) => response.json())
.then((json) => new Attachment(json.attachment))
.catch((errorMessage) => {
console.log(errorMessage);
});

return promise;
}

static deleteContainerLink(params) {
const promise = fetch(`/api/v1/attachments/link/${params.id}`, {
credentials: 'same-origin',
Expand Down Expand Up @@ -523,7 +542,7 @@ export default class AttachmentFetcher {
let jcampIds = oldSpcInfos.map((spc) => (spc.idx));
const fetchedFilesIdxs = json.files.map((file) => (file.id));
jcampIds = [...jcampIds, ...fetchedFilesIdxs];

return AttachmentFetcher.combineSpectra(jcampIds, curveIdx).then((res) => {
return json;
}).catch((errMsg) => {
Expand Down
14 changes: 14 additions & 0 deletions app/packs/src/stores/alt/actions/InboxActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,20 @@ class InboxActions {
};
}

bulkDeleteAttachments(attachmentIdsToDelete, fromUnsorted = false) {
return (dispatch) => {
AttachmentFetcher.bulkDeleteAttachments(attachmentIdsToDelete)
.then((result) => {
dispatch({
result,
fromUnsorted,
});
}).catch((errorMessage) => {
console.log(errorMessage);
});
};
}

deleteContainerLink(params) {
return (dispatch) => {
AttachmentFetcher.deleteContainerLink(params)
Expand Down
35 changes: 34 additions & 1 deletion app/packs/src/stores/alt/stores/InboxStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class InboxStore {
handleRemoveUnlinkedAttachmentFromList: InboxActions.removeUnlinkedAttachmentFromList,
handleRemoveDatasetFromList: InboxActions.removeDatasetFromList,
handleDeleteAttachment: InboxActions.deleteAttachment,
handleBulkDeleteAttachment: InboxActions.bulkDeleteAttachments,
handleDeleteContainer: InboxActions.deleteContainer,
handleBackToInbox: InboxActions.backToInbox,
handleDeleteContainerLink: InboxActions.deleteContainerLink,
Expand Down Expand Up @@ -242,6 +243,28 @@ class InboxStore {
}
}

handleBulkDeleteAttachment(payload) {
if (payload?.fromUnsorted) {
const { inbox } = this.state;

const updatedAttachments = inbox.unlinked_attachments.filter(
(attachment) => attachment.id !== payload?.result.id
);

this.setState({
inbox: {
...inbox,
unlinked_attachments: updatedAttachments,
},
});
this.countAttachments();
} else {
const { activeDeviceBoxId, currentContainerPage } = this.state;

InboxActions.fetchInboxContainer(activeDeviceBoxId, currentContainerPage);
}
}

handleDeleteContainerLink(result) {
const { currentPage, itemsPerPage } = this.state;
InboxActions.fetchInbox({ currentPage, itemsPerPage });
Expand All @@ -257,7 +280,17 @@ class InboxStore {
newInbox.children.splice(parentIndex, 1);
this.setState({ inbox: newInbox });
} else {
InboxActions.fetchInboxContainer(activeDeviceBoxId, currentContainerPage);
const updatedChildren = inbox.children.map((parent) => {
if (parent.children && parent.children.length > 0) {
const newParent = { ...parent };
newParent.children = parent.children.filter((child) => child.id !== result.id);
return newParent;
}
return parent;
});

const updatedInbox = { ...inbox, children: updatedChildren };
this.setState({ inbox: updatedInbox });
}
}

Expand Down

0 comments on commit 84c8806

Please sign in to comment.