diff --git a/packages/compass-data-modeling/src/store/diagram.spec.ts b/packages/compass-data-modeling/src/store/diagram.spec.ts index 0da0c2cf71d..f17ae1d7bff 100644 --- a/packages/compass-data-modeling/src/store/diagram.spec.ts +++ b/packages/compass-data-modeling/src/store/diagram.spec.ts @@ -4,6 +4,7 @@ import { applyEdit, getCurrentDiagramFromState, getCurrentModel, + getTypeNameForTelemetry, openDiagram, redoEdit, undoEdit, @@ -574,3 +575,30 @@ describe('Data Modeling store', function () { }); }); }); + +describe('getTypeNameForTelemetry', () => { + it('should return undefined when bsonType is undefined', () => { + const result = getTypeNameForTelemetry(undefined); + expect(result).to.be.undefined; + }); + + it('should return undefined when bsonType is an empty array', () => { + const result = getTypeNameForTelemetry([]); + expect(result).to.be.undefined; + }); + + it('should return the string when bsonType is a string', () => { + const result = getTypeNameForTelemetry('string'); + expect(result).to.equal('string'); + }); + + it('should return the single element when bsonType is an array with one element', () => { + const result = getTypeNameForTelemetry(['string']); + expect(result).to.equal('string'); + }); + + it('should return "mixed" when bsonType is an array with multiple elements', () => { + const result = getTypeNameForTelemetry(['string', 'number']); + expect(result).to.equal('mixed'); + }); +}); diff --git a/packages/compass-data-modeling/src/store/diagram.ts b/packages/compass-data-modeling/src/store/diagram.ts index 95c5ac4b63a..9be07203139 100644 --- a/packages/compass-data-modeling/src/store/diagram.ts +++ b/packages/compass-data-modeling/src/store/diagram.ts @@ -696,30 +696,70 @@ export function deleteRelationship( export function deleteCollection( ns: string -): DataModelingThunkAction { - return applyEdit({ type: 'RemoveCollection', ns }); +): DataModelingThunkAction { + return (dispatch, getState, { track }) => { + track('Data Modeling Collection Removed', { + source: 'side_panel', + }); + + dispatch(applyEdit({ type: 'RemoveCollection', ns })); + }; } export function updateCollectionNote( ns: string, note: string -): DataModelingThunkAction { +): DataModelingThunkAction { return applyEdit({ type: 'UpdateCollectionNote', ns, note }); } export function removeField( ns: string, field: FieldPath -): DataModelingThunkAction { - return applyEdit({ type: 'RemoveField', ns, field }); +): DataModelingThunkAction { + return (dispatch, getState, { track }) => { + track('Data Modeling Field Removed', { + source: 'side_panel', + }); + + dispatch(applyEdit({ type: 'RemoveField', ns, field })); + }; } export function renameField( ns: string, field: FieldPath, newName: string -): DataModelingThunkAction { - return applyEdit({ type: 'RenameField', ns, field, newName }); +): DataModelingThunkAction { + return (dispatch, getState, { track }) => { + track('Data Modeling Field Renamed', { + source: 'side_panel', + }); + + dispatch(applyEdit({ type: 'RenameField', ns, field, newName })); + }; +} + +/** + * @internal Exported for testing purposes only. + * If the field had a single type, we return that, otherwise 'mixed'. + */ +export function getTypeNameForTelemetry( + bsonType: string | string[] | undefined +): string | undefined { + if (!bsonType) { + return; + } + if (Array.isArray(bsonType)) { + if (bsonType.length === 0) { + return undefined; + } + if (bsonType.length === 1) { + return bsonType[0]; + } + return 'mixed'; + } + return bsonType; } export function changeFieldType( @@ -727,7 +767,7 @@ export function changeFieldType( fieldPath: FieldPath, newTypes: string[] ): DataModelingThunkAction { - return (dispatch, getState) => { + return (dispatch, getState, { track }) => { const collectionSchema = selectCurrentModelFromState( getState() ).collections.find((collection) => collection.ns === ns)?.jsonSchema; @@ -738,6 +778,13 @@ export function changeFieldType( }); if (!field) throw new Error('Field not found in schema'); const to = getSchemaWithNewTypes(field.jsonSchema, newTypes); + + track('Data Modeling Field Type Changed', { + source: 'side_panel', + from: getTypeNameForTelemetry(field.jsonSchema.bsonType), + to: getTypeNameForTelemetry(to.bsonType), + }); + dispatch( applyEdit({ type: 'ChangeFieldType', @@ -786,10 +833,10 @@ export function addCollection( ns?: string, position?: [number, number] ): DataModelingThunkAction< - boolean, + void, ApplyEditAction | ApplyEditFailedAction | CollectionSelectedAction > { - return (dispatch, getState) => { + return (dispatch, getState, { track }) => { const existingCollections = selectCurrentModelFromState( getState() ).collections; @@ -802,6 +849,10 @@ export function addCollection( }); } + track('Data Modeling Collection Added', { + source: 'toolbar', + }); + const edit: Omit< Extract, 'id' | 'timestamp' @@ -820,7 +871,6 @@ export function addCollection( position, }; dispatch(applyEdit(edit)); - return true; }; } diff --git a/packages/compass-telemetry/src/telemetry-events.ts b/packages/compass-telemetry/src/telemetry-events.ts index 3962d1272f7..f77b502c516 100644 --- a/packages/compass-telemetry/src/telemetry-events.ts +++ b/packages/compass-telemetry/src/telemetry-events.ts @@ -2919,6 +2919,42 @@ type CreateIndexStrategiesDocumentationClicked = CommonEvent<{ }; }>; +/** + * This event is fired when user adds a collection in a data modeling diagram. + * + * @category Data Modeling + */ +type DataModelingDiagramCollectionAdded = CommonEvent<{ + name: 'Data Modeling Collection Added'; + payload: { + source: 'toolbar'; + }; +}>; + +/** + * This event is fired when user removes a collection in a data modeling diagram. + * + * @category Data Modeling + */ +type DataModelingDiagramCollectionRemoved = CommonEvent<{ + name: 'Data Modeling Collection Removed'; + payload: { + source: 'side_panel'; + }; +}>; + +/** + * This event is fired when user renames a collection in a data modeling diagram. + * + * @category Data Modeling + */ +type DataModelingDiagramCollectionRenamed = CommonEvent<{ + name: 'Data Modeling Collection Renamed'; + payload: { + source: 'side_panel'; + }; +}>; + /** * This event is fired when a new data modeling diagram is created * @@ -2943,6 +2979,44 @@ type DataModelingDiagramExported = CommonEvent<{ }; }>; +/** + * This event is fired when user removes a field in a data modeling diagram. + * + * @category Data Modeling + */ +type DataModelingDiagramFieldRemoved = CommonEvent<{ + name: 'Data Modeling Field Removed'; + payload: { + source: 'side_panel'; + }; +}>; + +/** + * This event is fired when user renames a field in a data modeling diagram. + * + * @category Data Modeling + */ +type DataModelingDiagramFieldRenamed = CommonEvent<{ + name: 'Data Modeling Field Renamed'; + payload: { + source: 'side_panel'; + }; +}>; + +/** + * This event is fired when user changes a field type in a data modeling diagram. + * + * @category Data Modeling + */ +type DataModelingDiagramFieldTypeChanged = CommonEvent<{ + name: 'Data Modeling Field Type Changed'; + payload: { + source: 'side_panel'; + from?: string; + to?: string; + }; +}>; + /** * This event is fired when user imports data modeling diagram. * @@ -3064,7 +3138,18 @@ export type TelemetryEvent = | ConnectionRemovedEvent | CurrentOpShowOperationDetailsEvent | DatabaseCreatedEvent + | DataModelingDiagramCollectionAdded + | DataModelingDiagramCollectionRemoved + | DataModelingDiagramCollectionRenamed | DataModelingDiagramCreated + | DataModelingDiagramExported + | DataModelingDiagramFieldRemoved + | DataModelingDiagramFieldRenamed + | DataModelingDiagramFieldTypeChanged + | DataModelingDiagramImported + | DataModelingDiagramRelationshipAdded + | DataModelingDiagramRelationshipEdited + | DataModelingDiagramRelationshipDeleted | DeleteExportedEvent | DeleteExportOpenedEvent | DetailViewHideOperationDetailsEvent @@ -3161,10 +3246,5 @@ export type TelemetryEvent = | CreateIndexIndexSuggestionsCopied | CreateIndexStrategiesDocumentationClicked | UUIDEncounteredEvent - | DataModelingDiagramExported - | DataModelingDiagramImported - | DataModelingDiagramRelationshipAdded - | DataModelingDiagramRelationshipEdited - | DataModelingDiagramRelationshipDeleted | ContextMenuOpened | ContextMenuItemClicked;