From 064d5e05f518cc44ff859caa465e928ece052a4c Mon Sep 17 00:00:00 2001 From: naronchen Date: Fri, 20 Jun 2025 12:51:08 -0400 Subject: [PATCH 01/11] toggles work --- .gitignore | 1 + .../src/api/VersionCompareTiles.ts | 50 ++++++++++++------- .../src/api/VersionCompareVisualization.ts | 20 ++++++-- .../src/widgets/EnhancedElementsInspector.tsx | 29 ++++++++--- 4 files changed, 72 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 2435c323..9b15d9c8 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ pnpm-debug.log* .env.* packages/test-app-frontend/dist/ +*.DS_Store diff --git a/packages/changed-elements-react/src/api/VersionCompareTiles.ts b/packages/changed-elements-react/src/api/VersionCompareTiles.ts index 48d3952c..21259a40 100644 --- a/packages/changed-elements-react/src/api/VersionCompareTiles.ts +++ b/packages/changed-elements-react/src/api/VersionCompareTiles.ts @@ -40,6 +40,7 @@ export interface VersionDisplayOptions { hideUnchanged: boolean; hideRemoved: boolean; hideModified: boolean; + hideAdded: boolean; wantModified?: boolean; neverDrawn?: Set; changedModels?: Set; @@ -338,6 +339,9 @@ export class Provider return this._options && this._options.hideModified; } + private _wantHideAdded() { + return this._options && this._options?.hideAdded; + } /** * The overrides applied to the *primary* IModelConnection, to hilite inserted/updated elements. * This also takes into account never drawn elements passed via display options to the provider @@ -360,10 +364,11 @@ export class Provider ? true : undefined, }); + for (const elem of insertedElems) { // Check if user is emphasizing some elements, and if so, override said elements if (this._internalAlwaysDrawn.size === 0 || this._internalAlwaysDrawn.has(elem.id)) { - overrides.override({ elementId: elem.id, appearance: inserted }); + overrides.override({ elementId: elem.id, appearance: this._wantHideAdded() ? hiddenAppearance : inserted }); } } @@ -391,7 +396,14 @@ export class Provider for (const elem of updatedElems) { // Check if user is emphasizing some elements, and if so, only override said elements if (this._internalAlwaysDrawn.size === 0 || this._internalAlwaysDrawn.has(elem.id)) { - overrides.override({ elementId: elem.id, appearance: elem.indirect ? updatedIndirectly : updated }); + overrides.override({ + elementId: elem.id, + appearance: this._wantHideModified() + ? hiddenAppearance + : elem.indirect + ? updatedIndirectly + : updated + }); } } } @@ -471,23 +483,23 @@ export class Provider ); } - // Handle modified elements that are in secondary iModel - if (this._options?.wantModified && !this._wantHideModified()) { - const modifiedElemIds = new Set( - this.changedElems - .filter( - (entry: ChangedElement) => - entry.opcode === DbOpcode.Update && !neverDrawn.has(entry.id), - ) - .map((entry: ChangedElement) => entry.id), - ); - // Set override for the modified element ids with the given color - this._overrideSecondaryIModelElements( - ovrs, - modifiedElemIds, - VersionCompareVisualizationManager.colorModifiedTargetRgb(), - ); - } + // // Handle modified elements that are in secondary iModel + // if (this._options?.wantModified && !this._wantHideModified()) { + // const modifiedElemIds = new Set( + // this.changedElems + // .filter( + // (entry: ChangedElement) => + // entry.opcode === DbOpcode.Update && !neverDrawn.has(entry.id), + // ) + // .map((entry: ChangedElement) => entry.id), + // ); + // // Set override for the modified element ids with the given color + // this._overrideSecondaryIModelElements( + // ovrs, + // modifiedElemIds, + // VersionCompareVisualizationManager.colorModifiedTargetRgb(), + // ); + // } return ovrs; } diff --git a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts index 824534f6..ff33afd0 100644 --- a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts +++ b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts @@ -18,6 +18,7 @@ import { isVersionComparisonDisplayEnabled, Provider as VersionCompareProvider, updateVersionCompareDisplayEntries, updateVersionComparisonDisplayOptions, type VersionDisplayOptions } from "./VersionCompareTiles.js"; +import { FilterOptions } from "../SavedFiltersManager.js"; /** * Handles version compare visualization by using the VersionCompareTiles' provider @@ -86,6 +87,7 @@ export class VersionCompareVisualizationManager { hideUnchanged: false, hideRemoved: false, hideModified: false, + hideAdded: false, wantModified: _wantSecondaryModified, emphasized: true, }; @@ -100,6 +102,19 @@ export class VersionCompareVisualizationManager { }); } + public updateDisplayOptions = (options: FilterOptions) => { + if (options.wantAdded !== undefined) { + this.displayOptions.hideAdded = !options.wantAdded; + } + + if (options.wantModified !== undefined) { + this.displayOptions.hideModified = !options.wantModified; + } + + this.displayOptions.hideUnchanged = + options.wantUnchanged !== undefined ? !options.wantUnchanged : !this.displayOptions.hideUnchanged; + } + /** * Used to emphasize and focus on a list of elements instead of all changed elements in comparison * @param elements Elements to focus during visualization @@ -150,6 +165,7 @@ export class VersionCompareVisualizationManager { hideUnchanged: false, hideRemoved: false, hideModified: false, + hideAdded: false, }; await disableVersionComparisonDisplay(this._viewport); @@ -285,9 +301,7 @@ export class VersionCompareVisualizationManager { } /** Toggles the visibility of unchanged elements during comparison */ - public async toggleUnchangedVisibility(hide?: boolean): Promise { - this.displayOptions.hideUnchanged = - hide !== undefined ? hide : !this.displayOptions.hideUnchanged; + public async toggleUnchangedVisibility(): Promise { this.displayOptions.changedModels = this._changedModels; this.displayOptions.emphasized = true; diff --git a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx index a831cee7..11b20ccd 100644 --- a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx +++ b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx @@ -580,7 +580,8 @@ export class ChangedElementsListComponent extends Component { + if (entry.opcode === DbOpcode.Delete){ + return opts.wantDeleted; + } + if (entry.opcode === DbOpcode.Update) { + return this._modifiedEntryMatchesFilters(entry, opts); // @naron: is this needed? + } + return true; + } + + private _filterRemovedEntryWithOptions = (entry: ChangedElementEntry): boolean => { + // If the entry is deleted, we want to show it only if the filter options want deleted elements + return this._filterRemovedEntryWithGivenOptions(entry, this.state.filterOptions); + } + /** Obtains the children nodes of the models, creates their entries, and visualizes them. */ private _visualizeModelNodes = async (nodes: TreeNodeItem[], options?: FilterOptions): Promise => { // Handle model nodes: Get the children entries they already have into an array const filter = options - ? (entry: ChangedElementEntry) => this._filterEntryWithGivenOptions(entry, options) - : this._filterEntryWithOptions; + ? (entry: ChangedElementEntry) => this._filterRemovedEntryWithGivenOptions(entry, options) + : this._filterRemovedEntryWithOptions; const modelIds = new Set(nodes.map((value) => value.id)); const entries = this.props.dataProvider.getEntriesWithModelIds(modelIds, filter); const visualizationManager = this.props.manager.visualization?.getSingleViewVisualizationManager(); @@ -895,7 +911,7 @@ export class ChangedElementsListComponent extends Component Date: Mon, 23 Jun 2025 09:52:19 -0400 Subject: [PATCH 02/11] type of change filtering --- .../src/api/ChangedElementEntryCache.ts | 1 + .../src/api/VersionCompareTiles.ts | 38 +++++++++---------- .../src/widgets/EnhancedElementsInspector.tsx | 35 ++++++++--------- 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/packages/changed-elements-react/src/api/ChangedElementEntryCache.ts b/packages/changed-elements-react/src/api/ChangedElementEntryCache.ts index 158c820f..fa275080 100644 --- a/packages/changed-elements-react/src/api/ChangedElementEntryCache.ts +++ b/packages/changed-elements-react/src/api/ChangedElementEntryCache.ts @@ -54,6 +54,7 @@ export interface ChangedElementEntry extends ChangedElement { directChildren?: string[]; loaded: boolean; indirect?: boolean; + isTypeOfChangeFiltered?: boolean; } /** Cache for changed element entries that are maintained and populated with labels as we load labels with the cache */ diff --git a/packages/changed-elements-react/src/api/VersionCompareTiles.ts b/packages/changed-elements-react/src/api/VersionCompareTiles.ts index 21259a40..98aa2094 100644 --- a/packages/changed-elements-react/src/api/VersionCompareTiles.ts +++ b/packages/changed-elements-react/src/api/VersionCompareTiles.ts @@ -398,11 +398,11 @@ export class Provider if (this._internalAlwaysDrawn.size === 0 || this._internalAlwaysDrawn.has(elem.id)) { overrides.override({ elementId: elem.id, - appearance: this._wantHideModified() + appearance: this._wantHideModified() || elem.isTypeOfChangeFiltered ? hiddenAppearance : elem.indirect ? updatedIndirectly - : updated + : updated, }); } } @@ -483,23 +483,23 @@ export class Provider ); } - // // Handle modified elements that are in secondary iModel - // if (this._options?.wantModified && !this._wantHideModified()) { - // const modifiedElemIds = new Set( - // this.changedElems - // .filter( - // (entry: ChangedElement) => - // entry.opcode === DbOpcode.Update && !neverDrawn.has(entry.id), - // ) - // .map((entry: ChangedElement) => entry.id), - // ); - // // Set override for the modified element ids with the given color - // this._overrideSecondaryIModelElements( - // ovrs, - // modifiedElemIds, - // VersionCompareVisualizationManager.colorModifiedTargetRgb(), - // ); - // } + // Handle modified elements that are in secondary iModel + if (this._options?.wantModified && !this._wantHideModified()) { + const modifiedElemIds = new Set( + this.changedElems + .filter( + (entry: ChangedElement) => + entry.opcode === DbOpcode.Update && !neverDrawn.has(entry.id), + ) + .map((entry: ChangedElement) => entry.id), + ); + // Set override for the modified element ids with the given color + this._overrideSecondaryIModelElements( + ovrs, + modifiedElemIds, + VersionCompareVisualizationManager.colorModifiedTargetRgb(), + ); + } return ovrs; } diff --git a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx index 11b20ccd..a048c4e6 100644 --- a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx +++ b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx @@ -580,7 +580,7 @@ export class ChangedElementsListComponent extends Component { - return this._filterEntryWithGivenOptions(entry, this.state.filterOptions); - }; - - /** Returns true if filterOptions matches the entry. */ - private _filterEntryWithGivenOptions = (entry: ChangedElementEntry, opts: FilterOptions): boolean => { - return this._wantShowEntry(entry, opts); - }; - private _filterRemovedEntryWithGivenOptions = (entry: ChangedElementEntry, opts: FilterOptions): boolean => { + private _entryPassesFilter = (entry: ChangedElementEntry, opts: FilterOptions): boolean => { if (entry.opcode === DbOpcode.Delete){ return opts.wantDeleted; } if (entry.opcode === DbOpcode.Update) { - return this._modifiedEntryMatchesFilters(entry, opts); // @naron: is this needed? + if (!this._modifiedEntryMatchesFilters(entry, opts)){ + entry.isTypeOfChangeFiltered = true; + } else { + entry.isTypeOfChangeFiltered = false; + } } return true; } - private _filterRemovedEntryWithOptions = (entry: ChangedElementEntry): boolean => { + private _entryPassesFilterWithOptions = (entry: ChangedElementEntry): boolean => { // If the entry is deleted, we want to show it only if the filter options want deleted elements - return this._filterRemovedEntryWithGivenOptions(entry, this.state.filterOptions); + return this._entryPassesFilter(entry, this.state.filterOptions); } /** Obtains the children nodes of the models, creates their entries, and visualizes them. */ private _visualizeModelNodes = async (nodes: TreeNodeItem[], options?: FilterOptions): Promise => { // Handle model nodes: Get the children entries they already have into an array const filter = options - ? (entry: ChangedElementEntry) => this._filterRemovedEntryWithGivenOptions(entry, options) - : this._filterRemovedEntryWithOptions; + ? (entry: ChangedElementEntry) => this._entryPassesFilter(entry, options) + : this._entryPassesFilterWithOptions; const modelIds = new Set(nodes.map((value) => value.id)); const entries = this.props.dataProvider.getEntriesWithModelIds(modelIds, filter); const visualizationManager = this.props.manager.visualization?.getSingleViewVisualizationManager(); @@ -874,13 +869,13 @@ export class ChangedElementsListComponent extends Component this._filterEntryWithGivenOptions(entry, options) - : this._filterEntryWithOptions; + const filter = options + ? (entry: ChangedElementEntry) => this._entryPassesFilter(entry, options) + : this._entryPassesFilterWithOptions; // Visualize the filtered elements and focus const visualizationManager = this.props.manager.visualization?.getSingleViewVisualizationManager(); - await visualizationManager?.setFocusedElements(entries.filter(filterFunc)); + await visualizationManager?.setFocusedElements(entries.filter(filter)); }; /** Sets viewport visualization based on the given nodes and target/parent node. */ From 12a60105baadcdd1829fef2a7ccf9a65dfab6aa9 Mon Sep 17 00:00:00 2001 From: naronchen Date: Mon, 23 Jun 2025 10:07:16 -0400 Subject: [PATCH 03/11] changeset --- .changeset/loose-worms-tie.md | 5 +++++ .../src/widgets/EnhancedElementsInspector.tsx | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/loose-worms-tie.md diff --git a/.changeset/loose-worms-tie.md b/.changeset/loose-worms-tie.md new file mode 100644 index 00000000..2455da03 --- /dev/null +++ b/.changeset/loose-worms-tie.md @@ -0,0 +1,5 @@ +--- +"@itwin/changed-elements-react": patch +--- + +Changed elements gets hidden when toggling filters diff --git a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx index a048c4e6..629bfb8a 100644 --- a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx +++ b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx @@ -906,7 +906,7 @@ export class ChangedElementsListComponent extends Component Date: Thu, 26 Jun 2025 14:28:13 -0400 Subject: [PATCH 04/11] no as string --- .../src/NamedVersionSelector/NamedVersionSelector.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx b/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx index c89cf9f2..ae4fdf41 100644 --- a/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx +++ b/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx @@ -218,9 +218,9 @@ function NamedVersionSelector(props: Readonly): React const { iModel, manager, emptyState, manageVersions, feedbackUrl } = props; - const iTwinId = iModel.iTwinId as string; - const iModelId = iModel.iModelId as string; - const currentChangesetId = iModel.changeset.id; + const iTwinId = iModel.iTwinId ?? ""; + const iModelId = iModel.iModelId ?? ""; + const currentChangesetId = iModel.changeset.id ?? ""; const { isLoading, currentNamedVersion, entries, updateJobStatus } = useNamedVersionsList({ iTwinId, From afbd87511060735c0331b0031eba322ca7157e4e Mon Sep 17 00:00:00 2001 From: naronchen Date: Thu, 26 Jun 2025 17:30:16 -0400 Subject: [PATCH 05/11] added hidden elems & 2 filters --- .../NamedVersionSelector.tsx | 6 ++--- .../src/api/VersionCompareTiles.ts | 21 ++++++++++++--- .../src/api/VersionCompareVisualization.ts | 4 ++- .../src/widgets/EnhancedElementsInspector.tsx | 27 ++++++++++++------- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx b/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx index f4ae0243..bad97810 100644 --- a/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx +++ b/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx @@ -93,9 +93,9 @@ export function NamedVersionSelectorWidget(props: Readonly void> = []; private _options: VersionDisplayOptions | undefined; @@ -136,9 +137,11 @@ export class Provider options?: VersionDisplayOptions, targetIModelModels?: Set, targetIModelCategories?: Set, + hiddenElems?: ChangedElementEntry[], ) { this.iModel = iModel; this.changedElems = elems; + this.hiddenChangedElems = hiddenElems || []; this.viewport = vp; this._options = options; @@ -225,9 +228,11 @@ export class Provider /** * Set changed element entries to visualize * @param elems Changed elements + * @param hiddenElems Optional hidden changed elements to override display */ - public setChangedElems(elems: ChangedElementEntry[]) { + public setChangedElems(elems: ChangedElementEntry[], hiddenElems: ChangedElementEntry[] | undefined) { this.changedElems = elems; + this.hiddenChangedElems = hiddenElems || []; this.viewport.invalidateScene(); this.viewport.setFeatureOverrideProviderChanged(); refreshEvent.raiseEvent(); @@ -398,13 +403,22 @@ export class Provider if (this._internalAlwaysDrawn.size === 0 || this._internalAlwaysDrawn.has(elem.id)) { overrides.override({ elementId: elem.id, - appearance: this._wantHideModified() || elem.isTypeOfChangeFiltered + appearance: this._wantHideModified() ? hiddenAppearance : elem.indirect ? updatedIndirectly : updated, }); } + for (const elem of this.hiddenChangedElems){ + // If the user has hidden elements, we have to override them with the hidden appearance + if (this._internalNeverDrawn.size === 0 || this._internalNeverDrawn.has(elem.id)) { + overrides.override({ + elementId: elem.id, + appearance: hiddenAppearance, + }); + } + } } } @@ -939,10 +953,11 @@ export function isVersionComparisonDisplayUsingContextTools(vp: Viewport): boole export function updateVersionCompareDisplayEntries( vp: Viewport, entries: ChangedElementEntry[], + hiddenEntries: ChangedElementEntry[] | undefined, ): boolean { const existing = vp.findFeatureOverrideProviderOfType(Provider); if (undefined !== existing && existing instanceof Provider) { - existing.setChangedElems(entries); + existing.setChangedElems(entries, hiddenEntries); return true; } diff --git a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts index ff33afd0..888a0b5f 100644 --- a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts +++ b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts @@ -118,14 +118,16 @@ export class VersionCompareVisualizationManager { /** * Used to emphasize and focus on a list of elements instead of all changed elements in comparison * @param elements Elements to focus during visualization + * @param hiddenElements Optional list of elements that should not be shown in the visualization */ - public setFocusedElements = async (elements: ChangedElementEntry[] | undefined) => { + public setFocusedElements = async (elements: ChangedElementEntry[] | undefined, hiddenElements?: ChangedElementEntry[]) => { this._focusedElements = elements; updateVersionCompareDisplayEntries( this._viewport, this._focusedElements !== undefined ? this._focusedElements : this._changedElements, + hiddenElements, ); }; diff --git a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx index 629bfb8a..bcacfb57 100644 --- a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx +++ b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx @@ -811,18 +811,23 @@ export class ChangedElementsListComponent extends Component { + if (entry.opcode === DbOpcode.Update) { + if (!this._modifiedEntryMatchesFilters(entry, opts)){ + return true; + } + } + return false; + } + + private _entryModifiedFilterWithOptions = (entry: ChangedElementEntry): boolean => { + return this._entryModifiedFilter(entry, this.state.filterOptions); + } private _entryPassesFilter = (entry: ChangedElementEntry, opts: FilterOptions): boolean => { if (entry.opcode === DbOpcode.Delete){ return opts.wantDeleted; } - if (entry.opcode === DbOpcode.Update) { - if (!this._modifiedEntryMatchesFilters(entry, opts)){ - entry.isTypeOfChangeFiltered = true; - } else { - entry.isTypeOfChangeFiltered = false; - } - } return true; } @@ -839,8 +844,12 @@ export class ChangedElementsListComponent extends Component value.id)); const entries = this.props.dataProvider.getEntriesWithModelIds(modelIds, filter); + const modifiedFilter = options + ? (entry: ChangedElementEntry) => this._entryModifiedFilter(entry, options) + : this._entryModifiedFilterWithOptions; + const hiddenEntries = this.props.dataProvider.getEntriesWithModelIds(modelIds, modifiedFilter); const visualizationManager = this.props.manager.visualization?.getSingleViewVisualizationManager(); - await visualizationManager?.setFocusedElements(entries); + await visualizationManager?.setFocusedElements(entries, hiddenEntries); }; /** @@ -1124,7 +1133,7 @@ export class ChangedElementsListComponent extends Component Date: Fri, 27 Jun 2025 11:12:07 -0400 Subject: [PATCH 06/11] working on model nodes --- .../src/api/ChangesTreeDataProvider.ts | 34 +++++--- .../src/api/VersionCompareTiles.ts | 31 ++++---- .../src/api/VersionCompareVisualization.ts | 26 ++----- .../src/widgets/EnhancedElementsInspector.tsx | 77 ++++++++++++------- 4 files changed, 95 insertions(+), 73 deletions(-) diff --git a/packages/changed-elements-react/src/api/ChangesTreeDataProvider.ts b/packages/changed-elements-react/src/api/ChangesTreeDataProvider.ts index 44731dfd..a88989ed 100644 --- a/packages/changed-elements-react/src/api/ChangesTreeDataProvider.ts +++ b/packages/changed-elements-react/src/api/ChangesTreeDataProvider.ts @@ -31,6 +31,11 @@ export interface ModelElementChanges { typeOfChange: number; } +export interface EntryPartition { + visible: ChangedElementEntry[]; + hidden: ChangedElementEntry[]; +} + export function isModelElementChanges(input: unknown): input is ModelElementChanges { return !!input && typeof input === "object" @@ -1077,19 +1082,30 @@ export class ChangesTreeDataProvider implements ITreeDataProvider { return entries; } - /** Get entries with model ids based on a filter function. */ - public getEntriesWithModelIds( + /** Get entries with model ids based on a filter function. + * @param includeFilter Function to filter entries that should be visible + * @param hideFilter Function to filter entries that should be hidden + */ + public partitionByModelAndFilters( modelIds: Set, - filterFunc: (entry: ChangedElementEntry) => boolean, - ): ChangedElementEntry[] { - const entries = []; - for (const pair of this._elements) { - if (pair[1].modelId !== undefined && modelIds.has(pair[1].modelId) && filterFunc(pair[1])) { - entries.push(pair[1]); + includeFilter: (entry: ChangedElementEntry) => boolean, + hideFilter: (entry: ChangedElementEntry) => boolean, + ): EntryPartition { + const visible: ChangedElementEntry[] = []; + const hidden: ChangedElementEntry[] = []; + + for (const [, entry] of this._elements) { + if (!entry.modelId || !modelIds.has(entry.modelId)) continue; + + if (hideFilter(entry)){ + hidden.push(entry); + } + else if (includeFilter(entry)) { + visible.push(entry); } } - return entries; + return { visible, hidden }; } public getModelAllChildElementEntries(modelId: string): ChangedElementEntry[] { diff --git a/packages/changed-elements-react/src/api/VersionCompareTiles.ts b/packages/changed-elements-react/src/api/VersionCompareTiles.ts index e1c479cc..2906db0f 100644 --- a/packages/changed-elements-react/src/api/VersionCompareTiles.ts +++ b/packages/changed-elements-react/src/api/VersionCompareTiles.ts @@ -40,7 +40,6 @@ export interface VersionDisplayOptions { hideUnchanged: boolean; hideRemoved: boolean; hideModified: boolean; - hideAdded: boolean; wantModified?: boolean; neverDrawn?: Set; changedModels?: Set; @@ -344,9 +343,6 @@ export class Provider return this._options && this._options.hideModified; } - private _wantHideAdded() { - return this._options && this._options?.hideAdded; - } /** * The overrides applied to the *primary* IModelConnection, to hilite inserted/updated elements. * This also takes into account never drawn elements passed via display options to the provider @@ -373,7 +369,7 @@ export class Provider for (const elem of insertedElems) { // Check if user is emphasizing some elements, and if so, override said elements if (this._internalAlwaysDrawn.size === 0 || this._internalAlwaysDrawn.has(elem.id)) { - overrides.override({ elementId: elem.id, appearance: this._wantHideAdded() ? hiddenAppearance : inserted }); + overrides.override({ elementId: elem.id, appearance: inserted }); } } @@ -403,21 +399,20 @@ export class Provider if (this._internalAlwaysDrawn.size === 0 || this._internalAlwaysDrawn.has(elem.id)) { overrides.override({ elementId: elem.id, - appearance: this._wantHideModified() - ? hiddenAppearance - : elem.indirect + appearance: elem.indirect ? updatedIndirectly : updated, }); } - for (const elem of this.hiddenChangedElems){ - // If the user has hidden elements, we have to override them with the hidden appearance - if (this._internalNeverDrawn.size === 0 || this._internalNeverDrawn.has(elem.id)) { - overrides.override({ - elementId: elem.id, - appearance: hiddenAppearance, - }); - } + } + + for (const elem of this.hiddenChangedElems){ + // If the user has hidden elements, we have to override them with the hidden appearance + if (this._internalNeverDrawn.size === 0 || this._internalNeverDrawn.has(elem.id)) { + overrides.override({ + elementId: elem.id, + appearance: hiddenAppearance, + }); } } } @@ -952,12 +947,12 @@ export function isVersionComparisonDisplayUsingContextTools(vp: Viewport): boole export function updateVersionCompareDisplayEntries( vp: Viewport, - entries: ChangedElementEntry[], + visibleEntries: ChangedElementEntry[], hiddenEntries: ChangedElementEntry[] | undefined, ): boolean { const existing = vp.findFeatureOverrideProviderOfType(Provider); if (undefined !== existing && existing instanceof Provider) { - existing.setChangedElems(entries, hiddenEntries); + existing.setChangedElems(visibleEntries, hiddenEntries); return true; } diff --git a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts index 888a0b5f..4ec18915 100644 --- a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts +++ b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts @@ -87,7 +87,6 @@ export class VersionCompareVisualizationManager { hideUnchanged: false, hideRemoved: false, hideModified: false, - hideAdded: false, wantModified: _wantSecondaryModified, emphasized: true, }; @@ -102,26 +101,13 @@ export class VersionCompareVisualizationManager { }); } - public updateDisplayOptions = (options: FilterOptions) => { - if (options.wantAdded !== undefined) { - this.displayOptions.hideAdded = !options.wantAdded; - } - - if (options.wantModified !== undefined) { - this.displayOptions.hideModified = !options.wantModified; - } - - this.displayOptions.hideUnchanged = - options.wantUnchanged !== undefined ? !options.wantUnchanged : !this.displayOptions.hideUnchanged; - } - /** * Used to emphasize and focus on a list of elements instead of all changed elements in comparison - * @param elements Elements to focus during visualization + * @param visible Elements to focus during visualization * @param hiddenElements Optional list of elements that should not be shown in the visualization */ - public setFocusedElements = async (elements: ChangedElementEntry[] | undefined, hiddenElements?: ChangedElementEntry[]) => { - this._focusedElements = elements; + public setFocusedElements = async (visible: ChangedElementEntry[] | undefined, hiddenElements?: ChangedElementEntry[]) => { + this._focusedElements = visible; updateVersionCompareDisplayEntries( this._viewport, this._focusedElements !== undefined @@ -167,7 +153,6 @@ export class VersionCompareVisualizationManager { hideUnchanged: false, hideRemoved: false, hideModified: false, - hideAdded: false, }; await disableVersionComparisonDisplay(this._viewport); @@ -303,7 +288,10 @@ export class VersionCompareVisualizationManager { } /** Toggles the visibility of unchanged elements during comparison */ - public async toggleUnchangedVisibility(): Promise { + public async toggleUnchangedVisibility(options: FilterOptions): Promise { + this.displayOptions.hideUnchanged = + options.wantUnchanged !== undefined ? !options.wantUnchanged : !this.displayOptions.hideUnchanged; + this.displayOptions.changedModels = this._changedModels; this.displayOptions.emphasized = true; diff --git a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx index bcacfb57..914206f8 100644 --- a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx +++ b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx @@ -580,8 +580,7 @@ export class ChangedElementsListComponent extends Component { + private _hideFilter = (entry: ChangedElementEntry, opts: FilterOptions): boolean => { if (entry.opcode === DbOpcode.Update) { + // hide when the filter options do not want modified elements + if (!opts.wantModified) { + return true; + } + // hide when type of change filtering or advanced filtering is matched if (!this._modifiedEntryMatchesFilters(entry, opts)){ return true; } } - return false; - } - private _entryModifiedFilterWithOptions = (entry: ChangedElementEntry): boolean => { - return this._entryModifiedFilter(entry, this.state.filterOptions); + // hide when the filter options do not want added elements + if (entry.opcode === DbOpcode.Insert && !opts.wantAdded) { + return true; + } + return false; } private _entryPassesFilter = (entry: ChangedElementEntry, opts: FilterOptions): boolean => { @@ -831,25 +836,20 @@ export class ChangedElementsListComponent extends Component { - // If the entry is deleted, we want to show it only if the filter options want deleted elements - return this._entryPassesFilter(entry, this.state.filterOptions); - } - /** Obtains the children nodes of the models, creates their entries, and visualizes them. */ private _visualizeModelNodes = async (nodes: TreeNodeItem[], options?: FilterOptions): Promise => { // Handle model nodes: Get the children entries they already have into an array - const filter = options - ? (entry: ChangedElementEntry) => this._entryPassesFilter(entry, options) - : this._entryPassesFilterWithOptions; const modelIds = new Set(nodes.map((value) => value.id)); - const entries = this.props.dataProvider.getEntriesWithModelIds(modelIds, filter); - const modifiedFilter = options - ? (entry: ChangedElementEntry) => this._entryModifiedFilter(entry, options) - : this._entryModifiedFilterWithOptions; - const hiddenEntries = this.props.dataProvider.getEntriesWithModelIds(modelIds, modifiedFilter); + const opts = options ?? this.state.filterOptions; + + const includeFilter = (e: ChangedElementEntry) => e.opcode !== DbOpcode.Delete || opts.wantDeleted; + const hideFilter = (e: ChangedElementEntry) => this._hideFilter(e, opts); + + const { visible, hidden } = + this.props.dataProvider.partitionByModelAndFilters(modelIds, includeFilter, hideFilter); + const visualizationManager = this.props.manager.visualization?.getSingleViewVisualizationManager(); - await visualizationManager?.setFocusedElements(entries, hiddenEntries); + await visualizationManager?.setFocusedElements(visible, hidden); }; /** @@ -876,15 +876,39 @@ export class ChangedElementsListComponent extends Component => { // Get entries to visualize containing the relevant children entries as well const entries = targetNode ? this._getEntriesToVisualize(targetNode) : directChildNodes.map(nodeToEntry); + const opts = options ?? this.state.filterOptions; // Filter function for matching to the given filter options - const filter = options - ? (entry: ChangedElementEntry) => this._entryPassesFilter(entry, options) - : this._entryPassesFilterWithOptions; + const includeFilter = (e: ChangedElementEntry) => this._entryPassesFilter(e, opts); + const hideFilter = (e: ChangedElementEntry) => this._hideFilter(e, opts); // Visualize the filtered elements and focus const visualizationManager = this.props.manager.visualization?.getSingleViewVisualizationManager(); - await visualizationManager?.setFocusedElements(entries.filter(filter)); + await visualizationManager?.setFocusedElements(entries); + // const opts = options ?? this.state.filterOptions; + // const includeFilter = (e: ChangedElementEntry) => + // e.opcode !== DbOpcode.Delete || opts.wantDeleted; + // const hideFilter = (e: ChangedElementEntry) => this._hideFilter(e, opts); + + // const entriesToVis = targetNode + // ? this._getEntriesToVisualize(targetNode) + // : directChildNodes.map(nodeToEntry); + + // const visible: ChangedElementEntry[] = []; + // const hidden: ChangedElementEntry[] = []; + + // for (const e of entriesToVis) { + // if (hideFilter(e)) { + // hidden.push(e); + // } else if (includeFilter(e)) { + // visible.push(e); + // } + // } + + // await this.props.manager.visualization + // ?.getSingleViewVisualizationManager() + // ?.setFocusedElements(visible, hidden); + }; /** Sets viewport visualization based on the given nodes and target/parent node. */ @@ -1120,8 +1144,7 @@ export class ChangedElementsListComponent extends Component Date: Fri, 27 Jun 2025 13:54:46 -0400 Subject: [PATCH 07/11] works with elems nodes --- .../src/api/VersionCompareTiles.ts | 2 +- .../src/widgets/EnhancedElementsInspector.tsx | 34 ++++--------------- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/packages/changed-elements-react/src/api/VersionCompareTiles.ts b/packages/changed-elements-react/src/api/VersionCompareTiles.ts index 2906db0f..c0ab865a 100644 --- a/packages/changed-elements-react/src/api/VersionCompareTiles.ts +++ b/packages/changed-elements-react/src/api/VersionCompareTiles.ts @@ -408,7 +408,7 @@ export class Provider for (const elem of this.hiddenChangedElems){ // If the user has hidden elements, we have to override them with the hidden appearance - if (this._internalNeverDrawn.size === 0 || this._internalNeverDrawn.has(elem.id)) { + if (this._internalAlwaysDrawn.size === 0 || this._internalAlwaysDrawn.has(elem.id)) { overrides.override({ elementId: elem.id, appearance: hiddenAppearance, diff --git a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx index 914206f8..d0438a70 100644 --- a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx +++ b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx @@ -810,6 +810,7 @@ export class ChangedElementsListComponent extends Component { if (entry.opcode === DbOpcode.Update) { // hide when the filter options do not want modified elements @@ -829,7 +830,8 @@ export class ChangedElementsListComponent extends Component { + /** return true for entries we want to include */ + private _includeFilter = (entry: ChangedElementEntry, opts: FilterOptions): boolean => { if (entry.opcode === DbOpcode.Delete){ return opts.wantDeleted; } @@ -842,7 +844,7 @@ export class ChangedElementsListComponent extends Component value.id)); const opts = options ?? this.state.filterOptions; - const includeFilter = (e: ChangedElementEntry) => e.opcode !== DbOpcode.Delete || opts.wantDeleted; + const includeFilter = (e: ChangedElementEntry) => this._includeFilter(e, opts); const hideFilter = (e: ChangedElementEntry) => this._hideFilter(e, opts); const { visible, hidden } = @@ -879,36 +881,12 @@ export class ChangedElementsListComponent extends Component this._entryPassesFilter(e, opts); + const includeFilter = (e: ChangedElementEntry) => this._includeFilter(e, opts) && !this._hideFilter(e, opts); const hideFilter = (e: ChangedElementEntry) => this._hideFilter(e, opts); // Visualize the filtered elements and focus const visualizationManager = this.props.manager.visualization?.getSingleViewVisualizationManager(); - await visualizationManager?.setFocusedElements(entries); - // const opts = options ?? this.state.filterOptions; - // const includeFilter = (e: ChangedElementEntry) => - // e.opcode !== DbOpcode.Delete || opts.wantDeleted; - // const hideFilter = (e: ChangedElementEntry) => this._hideFilter(e, opts); - - // const entriesToVis = targetNode - // ? this._getEntriesToVisualize(targetNode) - // : directChildNodes.map(nodeToEntry); - - // const visible: ChangedElementEntry[] = []; - // const hidden: ChangedElementEntry[] = []; - - // for (const e of entriesToVis) { - // if (hideFilter(e)) { - // hidden.push(e); - // } else if (includeFilter(e)) { - // visible.push(e); - // } - // } - - // await this.props.manager.visualization - // ?.getSingleViewVisualizationManager() - // ?.setFocusedElements(visible, hidden); - + await visualizationManager?.setFocusedElements(entries.filter(includeFilter), entries.filter(hideFilter)); }; /** Sets viewport visualization based on the given nodes and target/parent node. */ From d41fecffe49149673d6209f58920d73bbab609e2 Mon Sep 17 00:00:00 2001 From: naronchen Date: Fri, 27 Jun 2025 15:52:18 -0400 Subject: [PATCH 08/11] cleanUp and fixes --- .../src/api/ChangedElementEntryCache.ts | 1 - .../src/api/ChangesTreeDataProvider.ts | 2 +- .../src/api/VersionCompareTiles.ts | 18 +++++++++--------- .../src/api/VersionCompareVisualization.ts | 4 ++-- .../src/widgets/EnhancedElementsInspector.tsx | 6 +++--- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/changed-elements-react/src/api/ChangedElementEntryCache.ts b/packages/changed-elements-react/src/api/ChangedElementEntryCache.ts index fa275080..158c820f 100644 --- a/packages/changed-elements-react/src/api/ChangedElementEntryCache.ts +++ b/packages/changed-elements-react/src/api/ChangedElementEntryCache.ts @@ -54,7 +54,6 @@ export interface ChangedElementEntry extends ChangedElement { directChildren?: string[]; loaded: boolean; indirect?: boolean; - isTypeOfChangeFiltered?: boolean; } /** Cache for changed element entries that are maintained and populated with labels as we load labels with the cache */ diff --git a/packages/changed-elements-react/src/api/ChangesTreeDataProvider.ts b/packages/changed-elements-react/src/api/ChangesTreeDataProvider.ts index a88989ed..c63beed6 100644 --- a/packages/changed-elements-react/src/api/ChangesTreeDataProvider.ts +++ b/packages/changed-elements-react/src/api/ChangesTreeDataProvider.ts @@ -1086,7 +1086,7 @@ export class ChangesTreeDataProvider implements ITreeDataProvider { * @param includeFilter Function to filter entries that should be visible * @param hideFilter Function to filter entries that should be hidden */ - public partitionByModelAndFilters( + public GetEntriesByModelIdsAndFilters( modelIds: Set, includeFilter: (entry: ChangedElementEntry) => boolean, hideFilter: (entry: ChangedElementEntry) => boolean, diff --git a/packages/changed-elements-react/src/api/VersionCompareTiles.ts b/packages/changed-elements-react/src/api/VersionCompareTiles.ts index c0ab865a..b8fb98e7 100644 --- a/packages/changed-elements-react/src/api/VersionCompareTiles.ts +++ b/packages/changed-elements-react/src/api/VersionCompareTiles.ts @@ -116,7 +116,7 @@ export class Provider private _treeRef2d: Reference | undefined; public readonly iModel: IModelConnection; public secondaryIModelOverrides: FeatureSymbology.Overrides; - public changedElems: ChangedElementEntry[]; + public visibleChangedElems: ChangedElementEntry[]; public hiddenChangedElems: ChangedElementEntry[]; public readonly viewport: Viewport; private readonly _removals: Array<() => void> = []; @@ -139,7 +139,7 @@ export class Provider hiddenElems?: ChangedElementEntry[], ) { this.iModel = iModel; - this.changedElems = elems; + this.visibleChangedElems = elems; this.hiddenChangedElems = hiddenElems || []; this.viewport = vp; this._options = options; @@ -230,7 +230,7 @@ export class Provider * @param hiddenElems Optional hidden changed elements to override display */ public setChangedElems(elems: ChangedElementEntry[], hiddenElems: ChangedElementEntry[] | undefined) { - this.changedElems = elems; + this.visibleChangedElems = elems; this.hiddenChangedElems = hiddenElems || []; this.viewport.invalidateScene(); this.viewport.setFeatureOverrideProviderChanged(); @@ -352,8 +352,8 @@ export class Provider this._wantHideUnchanged() ? hiddenAppearance : unchangedAppearance, ); - const insertedElems = this.changedElems.filter((entry: ChangedElement) => entry.opcode === DbOpcode.Insert); - const updatedElems = this.changedElems.filter((entry: ChangedElement) => entry.opcode === DbOpcode.Update); + const insertedElems = this.visibleChangedElems.filter((entry: ChangedElement) => entry.opcode === DbOpcode.Insert); + const updatedElems = this.visibleChangedElems.filter((entry: ChangedElement) => entry.opcode === DbOpcode.Update); const inserted = FeatureAppearance.fromJSON({ rgb: VersionCompareVisualizationManager.colorInsertedRgb(), @@ -475,7 +475,7 @@ export class Provider // Handle removed elements that are in secondary iModel if (!this._wantHideRemoved()) { const deletedElemIds = new Set( - this.changedElems + this.visibleChangedElems .filter( (entry: ChangedElement) => entry.opcode === DbOpcode.Delete && @@ -495,7 +495,7 @@ export class Provider // Handle modified elements that are in secondary iModel if (this._options?.wantModified && !this._wantHideModified()) { const modifiedElemIds = new Set( - this.changedElems + this.visibleChangedElems .filter( (entry: ChangedElement) => entry.opcode === DbOpcode.Update && !neverDrawn.has(entry.id), @@ -766,7 +766,7 @@ export class Provider public toJSON(): ProviderProps { return { - changedElems: this.changedElems, + changedElems: this.visibleChangedElems, options: this._options, internalAlwaysDrawn: this._internalAlwaysDrawn, internalNeverDrawn: this._internalNeverDrawn, @@ -783,7 +783,7 @@ export class Provider } public fromJSON(props: ProviderProps) { - this.changedElems = props.changedElems; + this.visibleChangedElems = props.changedElems; this._internalAlwaysDrawn = props.internalAlwaysDrawn; this._internalNeverDrawn = props.internalNeverDrawn; this._exclusive = props.exclusive; diff --git a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts index 4ec18915..34fa31c6 100644 --- a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts +++ b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts @@ -288,9 +288,9 @@ export class VersionCompareVisualizationManager { } /** Toggles the visibility of unchanged elements during comparison */ - public async toggleUnchangedVisibility(options: FilterOptions): Promise { + public async toggleUnchangedVisibility(hide?: boolean): Promise { this.displayOptions.hideUnchanged = - options.wantUnchanged !== undefined ? !options.wantUnchanged : !this.displayOptions.hideUnchanged; + hide !== undefined ? hide : !this.displayOptions.hideUnchanged; this.displayOptions.changedModels = this._changedModels; this.displayOptions.emphasized = true; diff --git a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx index d0438a70..fedae4b4 100644 --- a/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx +++ b/packages/changed-elements-react/src/widgets/EnhancedElementsInspector.tsx @@ -580,7 +580,7 @@ export class ChangedElementsListComponent extends Component this._hideFilter(e, opts); const { visible, hidden } = - this.props.dataProvider.partitionByModelAndFilters(modelIds, includeFilter, hideFilter); + this.props.dataProvider.GetEntriesByModelIdsAndFilters(modelIds, includeFilter, hideFilter); const visualizationManager = this.props.manager.visualization?.getSingleViewVisualizationManager(); await visualizationManager?.setFocusedElements(visible, hidden); @@ -1122,7 +1122,7 @@ export class ChangedElementsListComponent extends Component Date: Fri, 27 Jun 2025 16:16:33 -0400 Subject: [PATCH 09/11] lint --- .../src/api/VersionCompareVisualization.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts index 34fa31c6..86cf39e6 100644 --- a/packages/changed-elements-react/src/api/VersionCompareVisualization.ts +++ b/packages/changed-elements-react/src/api/VersionCompareVisualization.ts @@ -18,7 +18,6 @@ import { isVersionComparisonDisplayEnabled, Provider as VersionCompareProvider, updateVersionCompareDisplayEntries, updateVersionComparisonDisplayOptions, type VersionDisplayOptions } from "./VersionCompareTiles.js"; -import { FilterOptions } from "../SavedFiltersManager.js"; /** * Handles version compare visualization by using the VersionCompareTiles' provider From 9e58e13f9b7f297ef8eaa561483e86252a2b94c6 Mon Sep 17 00:00:00 2001 From: naronchen Date: Wed, 9 Jul 2025 17:15:42 -0400 Subject: [PATCH 10/11] added no named version state --- .../NamedVersionSelector.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx b/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx index bad97810..bc217e15 100644 --- a/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx +++ b/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx @@ -93,9 +93,13 @@ export function NamedVersionSelectorWidget(props: Readonly; + } + + const iTwinId = iModel.iTwinId; + const iModelId = iModel.iModelId; + const currentChangesetId = iModel.changeset.id; const { isLoading, currentNamedVersion, entries, updateJobStatus } = useNamedVersionsList({ iTwinId, @@ -220,6 +224,14 @@ function EmptyState(): ReactElement { ); } +function NoNamedVersionsState(): ReactElement { + return ( + + {t("VersionCompare:versionCompare.noNamedVersions")} + + ); +} + function LoadingState(): ReactElement { return ( From 3aa7d304e7c22248d10d0291a7efbc07a34be1b2 Mon Sep 17 00:00:00 2001 From: naronchen Date: Fri, 11 Jul 2025 15:00:37 -0400 Subject: [PATCH 11/11] error on empty imodel connection --- .../src/NamedVersionSelector/NamedVersionSelector.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx b/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx index bc217e15..a8dffaf9 100644 --- a/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx +++ b/packages/changed-elements-react/src/NamedVersionSelector/NamedVersionSelector.tsx @@ -94,7 +94,7 @@ export function NamedVersionSelectorWidget(props: Readonly; + throw new Error("Empty IModel Connection") } const iTwinId = iModel.iTwinId; @@ -224,14 +224,6 @@ function EmptyState(): ReactElement { ); } -function NoNamedVersionsState(): ReactElement { - return ( - - {t("VersionCompare:versionCompare.noNamedVersions")} - - ); -} - function LoadingState(): ReactElement { return (