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(