diff --git a/src/powerbi-visual/capabilities.json b/src/powerbi-visual/capabilities.json
index 715ae5a..db181e7 100644
--- a/src/powerbi-visual/capabilities.json
+++ b/src/powerbi-visual/capabilities.json
@@ -105,6 +105,9 @@
},
"isGhost": {
"type": { "bool": true }
+ },
+ "zoomOnFilter": {
+ "type": { "bool": true }
}
}
},
diff --git a/src/powerbi-visual/src/components/ViewerControls.vue b/src/powerbi-visual/src/components/ViewerControls.vue
index aef4f7a..7802e1a 100644
--- a/src/powerbi-visual/src/components/ViewerControls.vue
+++ b/src/powerbi-visual/src/components/ViewerControls.vue
@@ -5,6 +5,19 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/powerbi-visual/src/plugins/viewer.ts b/src/powerbi-visual/src/plugins/viewer.ts
index e88f962..1253ab7 100644
--- a/src/powerbi-visual/src/plugins/viewer.ts
+++ b/src/powerbi-visual/src/plugins/viewer.ts
@@ -37,8 +37,8 @@ export interface Hit {
export interface IViewerEvents {
ping: (message: string) => void
setSelection: (objectIds: string[]) => void
- resetFilter: (objectIds: string[], ghost: boolean) => void
- filterSelection: (objectIds: string[], ghost: boolean) => void
+ resetFilter: (objectIds: string[], ghost: boolean, zoom: boolean) => void
+ filterSelection: (objectIds: string[], ghost: boolean, zoom: boolean) => void
setViewMode: (viewMode: ViewMode) => void
colorObjectsByGroup: (
colorById: {
@@ -149,20 +149,24 @@ export class ViewerHandler {
}
}
- public filterSelection = (objectIds: string[], ghost: boolean) => {
+ public filterSelection = (objectIds: string[], ghost: boolean, zoom: boolean = true) => {
console.log('🔗 Handling filterSelection inside ViewerHandler')
if (objectIds) {
this.unIsolateObjects()
this.filteringState = this.filtering.isolateObjects(objectIds, 'powerbi', true, ghost)
- this.zoomObjects(objectIds, true)
+ if (zoom) {
+ this.zoomObjects(objectIds, true)
+ }
}
}
- public resetFilter = (objectIds: string[], ghost: boolean) => {
+ public resetFilter = (objectIds: string[], ghost: boolean, zoom: boolean = true) => {
console.log('🔗 Handling filterSelection inside ViewerHandler')
if (objectIds) {
this.isolateObjects(objectIds, ghost)
- this.zoomObjects(objectIds, true)
+ if (zoom) {
+ this.zoomObjects(objectIds, true)
+ }
}
}
diff --git a/src/powerbi-visual/src/store/visualStore.ts b/src/powerbi-visual/src/store/visualStore.ts
index 1ed1672..c8793da 100644
--- a/src/powerbi-visual/src/store/visualStore.ts
+++ b/src/powerbi-visual/src/store/visualStore.ts
@@ -36,6 +36,7 @@ export const useVisualStore = defineStore('visualStore', () => {
const isOrthoProjection = ref(false)
const isGhostActive = ref(true)
const isNavbarHidden = ref(false)
+ const isZoomOnFilterActive = ref(true)
const commonError = ref(undefined)
@@ -165,13 +166,13 @@ export const useVisualStore = defineStore('visualStore', () => {
if (dataInput.value.selectedIds.length > 0) {
isFilterActive.value = true
- viewerEmit.value('filterSelection', dataInput.value.selectedIds, isGhostActive.value)
+ viewerEmit.value('filterSelection', dataInput.value.selectedIds, isGhostActive.value, isZoomOnFilterActive.value)
} else {
isFilterActive.value = false
latestColorBy.value = dataInput.value.colorByIds
// Only apply filtering if object IDs are available, otherwise show all objects normally
if (fieldInputState.value.objectIds && dataInput.value.objectIds && dataInput.value.objectIds.length > 0) {
- viewerEmit.value('resetFilter', dataInput.value.objectIds, isGhostActive.value)
+ viewerEmit.value('resetFilter', dataInput.value.objectIds, isGhostActive.value, isZoomOnFilterActive.value)
} else {
// No object IDs provided - show all objects without any filtering
viewerEmit.value('unIsolateObjects')
@@ -247,6 +248,22 @@ export const useVisualStore = defineStore('visualStore', () => {
})
}
+ const writeZoomOnFilterToFile = () => {
+ // NOTE: need skipping the update function, it resets the viewer state unneccessarily.
+ postFileSaveSkipNeeded.value = true
+ host.value.persistProperties({
+ merge: [
+ {
+ objectName: 'camera',
+ properties: {
+ zoomOnFilter: isZoomOnFilterActive.value
+ },
+ selector: null
+ }
+ ]
+ })
+ }
+
const writeViewModeToFile = (viewMode: ViewMode) => {
// NOTE: need skipping the update function, it resets the viewer state unneccessarily.
postFileSaveSkipNeeded.value = true
@@ -353,6 +370,10 @@ export const useVisualStore = defineStore('visualStore', () => {
isGhostActive.value = val
}
+ const setIsZoomOnFilterActive = (val: boolean) => {
+ isZoomOnFilterActive.value = val
+ }
+
const setPostFileSaveSkipNeeded = (newValue: boolean) => (postFileSaveSkipNeeded.value = newValue)
const setPostClickSkipNeeded = (newValue: boolean) => (postClickSkipNeeded.value = newValue)
@@ -366,7 +387,7 @@ export const useVisualStore = defineStore('visualStore', () => {
const resetFilters = () => {
// Only apply filtering if object IDs are available, otherwise show all objects normally
if (fieldInputState.value.objectIds && dataInput.value && dataInput.value.objectIds && dataInput.value.objectIds.length > 0) {
- viewerEmit.value('resetFilter', dataInput.value.objectIds, isGhostActive.value)
+ viewerEmit.value('resetFilter', dataInput.value.objectIds, isGhostActive.value, isZoomOnFilterActive.value)
} else {
// No object IDs provided - show all objects without any filtering
viewerEmit.value('unIsolateObjects')
@@ -395,13 +416,13 @@ export const useVisualStore = defineStore('visualStore', () => {
// Restore selection filters if they exist
if (dataInput.value.selectedIds.length > 0) {
isFilterActive.value = true
- viewerEmit.value('filterSelection', dataInput.value.selectedIds, isGhostActive.value)
+ viewerEmit.value('filterSelection', dataInput.value.selectedIds, isGhostActive.value, isZoomOnFilterActive.value)
} else {
isFilterActive.value = false
latestColorBy.value = dataInput.value.colorByIds
// Only apply filtering if object IDs are available, otherwise show all objects normally
if (fieldInputState.value.objectIds && dataInput.value.objectIds && dataInput.value.objectIds.length > 0) {
- viewerEmit.value('resetFilter', dataInput.value.objectIds, isGhostActive.value)
+ viewerEmit.value('resetFilter', dataInput.value.objectIds, isGhostActive.value, isZoomOnFilterActive.value)
} else {
// No object IDs provided - show all objects without any filtering
viewerEmit.value('unIsolateObjects')
@@ -443,6 +464,7 @@ export const useVisualStore = defineStore('visualStore', () => {
isOrthoProjection,
isGhostActive,
isNavbarHidden,
+ isZoomOnFilterActive,
latestAvailableVersion,
isConnectorUpToDate,
commonError,
@@ -450,6 +472,7 @@ export const useVisualStore = defineStore('visualStore', () => {
setLatestAvailableVersion,
setIsOrthoProjection,
setIsGhost,
+ setIsZoomOnFilterActive,
setFormattingSettings,
setBrandingHidden,
setNavbarHidden,
@@ -466,6 +489,7 @@ export const useVisualStore = defineStore('visualStore', () => {
writeObjectsToFile,
writeCameraViewToFile,
writeIsGhostToFile,
+ writeZoomOnFilterToFile,
writeIsOrthoToFile,
writeViewModeToFile,
writeCameraPositionToFile,
diff --git a/src/powerbi-visual/src/visual.ts b/src/powerbi-visual/src/visual.ts
index 2f6847f..c828d18 100644
--- a/src/powerbi-visual/src/visual.ts
+++ b/src/powerbi-visual/src/visual.ts
@@ -196,6 +196,16 @@ export class Visual implements IVisual {
)
}
+ if (camera && 'zoomOnFilter' in camera) {
+ console.log(
+ `Zoom on filter?: ${options.dataViews[0].metadata.objects.camera?.zoomOnFilter as boolean}`
+ )
+
+ visualStore.setIsZoomOnFilterActive(
+ options.dataViews[0].metadata.objects.camera?.zoomOnFilter as boolean
+ )
+ }
+
// get receive info from file for mixpanel
try {
const receiveInfoFromFile = JSON.parse(