From 634bf488dea48325329442c34cca3ad8487cf04c Mon Sep 17 00:00:00 2001 From: Mike Nguyen Date: Fri, 30 Aug 2024 14:11:59 -0400 Subject: [PATCH 1/3] feat: add feature tracking based off uievent --- packages/itwin/measure-tools/README.md | 57 +++++++++++++++++++ .../src/ui-2.0/MeasureToolsUiProvider.tsx | 10 +++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/packages/itwin/measure-tools/README.md b/packages/itwin/measure-tools/README.md index 689c00424..e623edc0d 100644 --- a/packages/itwin/measure-tools/README.md +++ b/packages/itwin/measure-tools/README.md @@ -99,3 +99,60 @@ An application can further customize UI event behavior by registering override h A concrete example of this customization is an application that has measurements organized into multiple groups. One group may be "frozen" due to some application state (state that the measure-tools library may be unaware of) and should not be cleared by the clear measurements tool. So the application would register a custom UI event handler that would cause those measurements to be ignored when the clear measurement tool is invoked. + +### Usage Tracking + +This package allows consumers to track the usage of specific features. + +This can be achieved by passing `onFeatureUsed` function to `MeasureToolsUiProvider`. The function is invoked with the information about the feature being used. The feature information is based off Feature interface (that can be imported from `"@itwin/measure-tools-react"`) + +``` +export interface Feature { + name: string; + guid: GuidString; + metaData?: Map; +} +``` + +As an example, for Measure Distance, we will have + +``` +{ + name: "CRT_Tools_MeasureDistance", + guid: "10e474ee-9af8-4262-a505-77c9d896b065", +} +``` + +### Example for Usage Tracking + +In this case, we create a sample [Itwin Viewer](https://www.npmjs.com/package/@itwin/web-viewer-react) and configure `MeasureToolsUiProvider` + +```ts +import { Feature, MeasureToolsUiItemsProvider } from "@itwin/measure-tools-react"; + +const App: React.FC = () => { + // Viewer Setup here... + return ( +
+ { + console.log(`MeasureTools [${feature.name}] used`); + }, + }), + ]} + /> +
+ ); +}; + +export default App; +``` diff --git a/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx b/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx index 20dbe3107..6a768438c 100644 --- a/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx +++ b/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx @@ -17,6 +17,7 @@ import { MeasureToolDefinitions } from "../tools/MeasureToolDefinitions"; import type { RecursiveRequired } from "../utils/types"; import { MeasurementPropertyWidget, MeasurementPropertyWidgetId } from "./MeasurementPropertyWidget"; import { IModelApp } from "@itwin/core-frontend"; +import { Feature, FeatureTracking } from "../measure-tools-react"; // Note: measure tools cannot pick geometry when a sheet view is active to snap to and therefore must be hidden // to avoid giving the user the impression they should work @@ -32,11 +33,15 @@ export interface MeasureToolsUiProviderOptions { // If we check for sheet to 3d transformation when measuring in sheets enableSheetMeasurement?: boolean; stageUsageList?: string[]; + // Callback that is invoked when a tracked feature is used. + onFeatureUsed?: (feature: Feature) => void; } export class MeasureToolsUiItemsProvider implements UiItemsProvider { public readonly id = "MeasureToolsUiItemsProvider"; - private _props: RecursiveRequired; + private _props: Omit, 'onFeatureUsed'> & { + onFeatureUsed?: (feature: Feature) => void; + }; constructor(props?: MeasureToolsUiProviderOptions) { this._props = { @@ -48,7 +53,10 @@ export class MeasureToolsUiItemsProvider implements UiItemsProvider { }, enableSheetMeasurement: props?.enableSheetMeasurement ?? false, stageUsageList: props?.stageUsageList ?? [StageUsage.General], + onFeatureUsed: props?.onFeatureUsed, }; + if (!FeatureTracking.onFeature.numberOfListeners && this._props.onFeatureUsed) + FeatureTracking.onFeature.addListener(this._props.onFeatureUsed); } public provideToolbarItems( From b0f3dc3fca4e9dbdf076b1ef743509903e8e9cd6 Mon Sep 17 00:00:00 2001 From: Mike Nguyen Date: Fri, 6 Sep 2024 14:55:36 -0400 Subject: [PATCH 2/3] fix: remove onFeaturedUsed from _props --- .../measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx b/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx index 6a768438c..d8b440107 100644 --- a/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx +++ b/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx @@ -39,9 +39,7 @@ export interface MeasureToolsUiProviderOptions { export class MeasureToolsUiItemsProvider implements UiItemsProvider { public readonly id = "MeasureToolsUiItemsProvider"; - private _props: Omit, 'onFeatureUsed'> & { - onFeatureUsed?: (feature: Feature) => void; - }; + private _props: Omit, 'onFeatureUsed'> constructor(props?: MeasureToolsUiProviderOptions) { this._props = { @@ -53,10 +51,9 @@ export class MeasureToolsUiItemsProvider implements UiItemsProvider { }, enableSheetMeasurement: props?.enableSheetMeasurement ?? false, stageUsageList: props?.stageUsageList ?? [StageUsage.General], - onFeatureUsed: props?.onFeatureUsed, }; - if (!FeatureTracking.onFeature.numberOfListeners && this._props.onFeatureUsed) - FeatureTracking.onFeature.addListener(this._props.onFeatureUsed); + if (!FeatureTracking.onFeature.numberOfListeners && props?.onFeatureUsed) + FeatureTracking.onFeature.addListener(props?.onFeatureUsed); } public provideToolbarItems( From 5afb9d4dfb1ab3713ce2b98a434e6527b9b0fa6f Mon Sep 17 00:00:00 2001 From: Mike Nguyen Date: Fri, 6 Sep 2024 15:28:30 -0400 Subject: [PATCH 3/3] refactor: add missing semicolon --- .../itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx b/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx index d8b440107..aa5c00a57 100644 --- a/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx +++ b/packages/itwin/measure-tools/src/ui-2.0/MeasureToolsUiProvider.tsx @@ -39,7 +39,7 @@ export interface MeasureToolsUiProviderOptions { export class MeasureToolsUiItemsProvider implements UiItemsProvider { public readonly id = "MeasureToolsUiItemsProvider"; - private _props: Omit, 'onFeatureUsed'> + private _props: Omit, 'onFeatureUsed'>; constructor(props?: MeasureToolsUiProviderOptions) { this._props = {