diff --git a/packages/compass-crud/src/components/bulk-delete-modal.tsx b/packages/compass-crud/src/components/bulk-delete-modal.tsx index fa5336cbaf2..e05e8055141 100644 --- a/packages/compass-crud/src/components/bulk-delete-modal.tsx +++ b/packages/compass-crud/src/components/bulk-delete-modal.tsx @@ -37,7 +37,7 @@ const documentContainerStyles = css({ }); const modalBodySpacingStyles = css({ - marginTop: spacing[3], + marginTop: spacing[3] - spacing[1], // see queryBarStyles below paddingLeft: spacing[5], display: 'flex', flexDirection: 'column', @@ -49,6 +49,7 @@ const queryBarStyles = css({ flexDirection: 'row', alignItems: 'center', gap: spacing[3], + marginTop: spacing[1], // don't cut off the focus/hover ring on the Export button }); const exportToLanguageButtonStyles = css({ diff --git a/packages/compass-crud/src/stores/crud-store.ts b/packages/compass-crud/src/stores/crud-store.ts index 76e3e379b10..29c7179061b 100644 --- a/packages/compass-crud/src/stores/crud-store.ts +++ b/packages/compass-crud/src/stores/crud-store.ts @@ -1102,6 +1102,10 @@ class CrudStoreImpl } async openBulkUpdateDialog() { + track('Bulk Update Opened', { + isUpdatePreviewSupported: this.state.isUpdatePreviewSupported, + }); + await this.updateBulkUpdatePreview('{ $set: { } }'); this.setState({ bulkUpdate: { @@ -1224,6 +1228,10 @@ class CrudStoreImpl } async runBulkUpdate() { + track('Bulk Update Executed', { + isUpdatePreviewSupported: this.state.isUpdatePreviewSupported, + }); + this.closeBulkUpdateDialog(); // keep the filter count around for the duration of the toast @@ -1826,6 +1834,8 @@ class CrudStoreImpl } openBulkDeleteDialog() { + track('Bulk Delete Opened'); + const PREVIEW_DOCS = 5; this.setState({ @@ -1880,6 +1890,8 @@ class CrudStoreImpl } async runBulkDelete() { + track('Bulk Delete Executed'); + const { affected } = this.state.bulkDelete; this.closeBulkDeleteDialog(); @@ -1919,6 +1931,10 @@ class CrudStoreImpl } async saveUpdateQuery(name: string): Promise { + track('Bulk Update Favorited', { + isUpdatePreviewSupported: this.state.isUpdatePreviewSupported, + }); + const { filter } = this.state.query; let update; try { diff --git a/packages/compass-e2e-tests/tests/collection-bulk-delete.test.ts b/packages/compass-e2e-tests/tests/collection-bulk-delete.test.ts index b8360ce7b7b..b9aa58a6df0 100644 --- a/packages/compass-e2e-tests/tests/collection-bulk-delete.test.ts +++ b/packages/compass-e2e-tests/tests/collection-bulk-delete.test.ts @@ -36,7 +36,7 @@ describe('Bulk Delete', () => { }); it('deletes documents matching a filter', async function () { - //const telemetryEntry = await browser.listenForTelemetryEvents(telemetry); + const telemetryEntry = await browser.listenForTelemetryEvents(telemetry); // Set a query that we'll use. await browser.runFindOperation('Documents', '{ i: 5 }'); @@ -45,6 +45,10 @@ describe('Bulk Delete', () => { await browser.clickVisible(Selectors.OpenBulkDeleteButton); await browser.$(Selectors.BulkDeleteModal).waitForDisplayed(); + // Check the telemetry + const openedEvent = await telemetryEntry('Bulk Delete Opened'); + expect(openedEvent).to.deep.equal({}); + // Make sure the query is shown in the modal. expect( await browser.$(Selectors.BulkDeleteModalReadonlyFilter).getText() @@ -71,6 +75,10 @@ describe('Bulk Delete', () => { await browser.clickVisible(Selectors.ConfirmationModalConfirmButton()); await browser.runFindOperation('Documents', '{ i: 5 }'); + // Check the telemetry + const executedEvent = await telemetryEntry('Bulk Delete Executed'); + expect(executedEvent).to.deep.equal({}); + // The success toast is displayed await browser.$(Selectors.BulkDeleteSuccessToast).waitForDisplayed(); @@ -93,8 +101,6 @@ describe('Bulk Delete', () => { }); it('does not delete documents when cancelled', async function () { - //const telemetryEntry = await browser.listenForTelemetryEvents(telemetry); - // Set a query that we'll use. await browser.runFindOperation('Documents', '{ i: 5 }'); @@ -129,4 +135,52 @@ describe('Bulk Delete', () => { await browser.$(Selectors.DocumentListActionBarMessage).getText() ).to.equal('1 – 1 of 1'); }); + + it('can export a delete query', async function () { + if (process.env.COMPASS_E2E_DISABLE_CLIPBOARD_USAGE === 'true') { + this.skip(); + } + + const telemetryEntry = await browser.listenForTelemetryEvents(telemetry); + + // Set a query that we'll use. + await browser.runFindOperation('Documents', '{ i: 5 }'); + + // Open the modal. + await browser.clickVisible(Selectors.OpenBulkDeleteButton); + await browser.$(Selectors.BulkDeleteModal).waitForDisplayed(); + + // Click the export button + await browser.clickVisible(Selectors.BulkDeleteModalExportButton); + + const openedEvent = await telemetryEntry('Delete Export Opened'); + expect(openedEvent).to.deep.equal({}); + + const text = await browser.exportToLanguage('Python', { + includeImportStatements: true, + includeDriverSyntax: true, + useBuilders: false, + }); + expect(text).to.equal(`from pymongo import MongoClient + +# Requires the PyMongo package. +# https://api.mongodb.com/python/current + +client = MongoClient('mongodb://localhost:27091/test') +filter={ + 'i': 5 +} + +result = client['test']['numbers'].delete_many( + filter=filter +)`); + + const exportedEvent = await telemetryEntry('Delete Exported'); + expect(exportedEvent).to.deep.equal({ + language: 'python', + with_builders: false, + with_drivers_syntax: true, + with_import_statements: true, + }); + }); }); diff --git a/packages/compass-e2e-tests/tests/collection-bulk-update.test.ts b/packages/compass-e2e-tests/tests/collection-bulk-update.test.ts index 17dafee7445..26566d1a4aa 100644 --- a/packages/compass-e2e-tests/tests/collection-bulk-update.test.ts +++ b/packages/compass-e2e-tests/tests/collection-bulk-update.test.ts @@ -36,7 +36,7 @@ describe('Bulk Update', () => { }); it('updates documents matching a filter', async function () { - //const telemetryEntry = await browser.listenForTelemetryEvents(telemetry); + const telemetryEntry = await browser.listenForTelemetryEvents(telemetry); // Set a query that we'll use. await browser.runFindOperation('Documents', '{ i: 5 }'); @@ -45,6 +45,12 @@ describe('Bulk Update', () => { await browser.clickVisible(Selectors.OpenBulkUpdateButton); await browser.$(Selectors.BulkUpdateModal).waitForDisplayed(); + // Check the telemetry + const openedEvent = await telemetryEntry('Bulk Update Opened'); + expect(openedEvent).to.deep.equal({ + isUpdatePreviewSupported: true, + }); + // Make sure the query is shown in the modal. expect( await browser.$(Selectors.BulkUpdateReadonlyFilter).getText() @@ -101,7 +107,11 @@ describe('Bulk Update', () => { .$(Selectors.BulkUpdateSuccessToast) .waitForDisplayed({ reverse: true }); - // TODO(COMPASS-7388): Check the telemetry once we add it + // Check the telemetry + const executedEvent = await telemetryEntry('Bulk Update Executed'); + expect(executedEvent).to.deep.equal({ + isUpdatePreviewSupported: true, + }); await browser.runFindOperation('Documents', '{ i: 5, foo: "bar" }'); const modifiedDocument = await browser.$(Selectors.DocumentListEntry); @@ -111,6 +121,8 @@ describe('Bulk Update', () => { }); it('can save an update query as a favourite and return to it', async function () { + const telemetryEntry = await browser.listenForTelemetryEvents(telemetry); + // Set a query that we'll use. await browser.runFindOperation('Documents', '{ i: { $gt: 5 } }'); @@ -136,6 +148,12 @@ describe('Bulk Update', () => { await browser.$(Selectors.BulkUpdateFavouriteSaveButton).waitForEnabled(); await browser.clickVisible(Selectors.BulkUpdateFavouriteSaveButton); + // Check the telemetry + const favoritedEvent = await telemetryEntry('Bulk Update Favorited'); + expect(favoritedEvent).to.deep.equal({ + isUpdatePreviewSupported: true, + }); + // Close the modal await browser.clickVisible(Selectors.BulkUpdateCancelButton); diff --git a/packages/compass-export-to-language/src/components/modal.tsx b/packages/compass-export-to-language/src/components/modal.tsx index b79424c51cd..64128241496 100644 --- a/packages/compass-export-to-language/src/components/modal.tsx +++ b/packages/compass-export-to-language/src/components/modal.tsx @@ -151,13 +151,19 @@ const ExportToLanguageModal: React.FunctionComponent< const [wasOpen, setWasOpen] = useState(false); useEffect(() => { + const trackingEvent = + mode === 'Update Query' + ? 'Update Export Opened' + : mode === 'Delete Query' + ? 'Delete Export Opened' + : mode === 'Query' + ? 'Query Export Opened' + : 'Aggregation Export Opened'; + if (modalOpen && !wasOpen) { - track( - mode === 'Query' ? 'Query Export Opened' : 'Aggregation Export Opened', - { - ...stageCountForTelemetry(inputExpression), - } - ); + track(trackingEvent, { + ...stageCountForTelemetry(inputExpression), + }); track('Screen', { name: 'export_to_language_modal' }); } @@ -165,7 +171,16 @@ const ExportToLanguageModal: React.FunctionComponent< }, [modalOpen, wasOpen, mode, inputExpression]); function trackCopiedOutput() { - track(mode === 'Query' ? 'Query Exported' : 'Aggregation Exported', { + const trackingEvent = + mode === 'Update Query' + ? 'Update Exported' + : mode === 'Delete Query' + ? 'Delete Exported' + : mode === 'Query' + ? 'Query Exported' + : 'Aggregation Exported'; + + track(trackingEvent, { language: outputLanguage, with_import_statements: includeImports, with_drivers_syntax: includeDrivers, diff --git a/packages/compass-query-bar/src/components/query-history/favorite-list.tsx b/packages/compass-query-bar/src/components/query-history/favorite-list.tsx index cda646d6c62..40d4c788435 100644 --- a/packages/compass-query-bar/src/components/query-history/favorite-list.tsx +++ b/packages/compass-query-bar/src/components/query-history/favorite-list.tsx @@ -46,6 +46,7 @@ const FavoriteItem = ({ track('Query History Favorite Used', { id: query._id, screen: 'documents', + isUpdateQuery, }); if (isDisabled) { @@ -70,9 +71,10 @@ const FavoriteItem = ({ track('Query History Favorite Removed', { id: query._id, screen: 'documents', + isUpdateQuery, }); onDelete(query._id); - }, [onDelete, query._id]); + }, [onDelete, query._id, isUpdateQuery]); return ( { - track('Query History Favorite Added'); + track('Query History Favorite Added', { isUpdateQuery }); void onFavorite(query, name); }, - [query, onFavorite] + [query, onFavorite, isUpdateQuery] ); return (