diff --git a/CHANGELOG.md b/CHANGELOG.md index 4db3f3299dc5..4a497ec2540c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -137,6 +137,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [BUG][Multiple Datasource] Validation succeed as long as status code in response is 200 ([#6399](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6399)) - [BUG][Multiple Datasource] Fix on data source selectable and readonly component are not consistent ([#6545]https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6545) - [BUG][Multiple Datasource] Add validation for title length to be no longer than 32 characters [#6452](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6452)) +- [BUG][VisBuilder] Fix filter and query bugs ([#6460](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6460)) ### 🚞 Infrastructure diff --git a/src/plugins/vis_builder/public/application/components/top_nav.tsx b/src/plugins/vis_builder/public/application/components/top_nav.tsx index 768f2db35465..833edf3044b9 100644 --- a/src/plugins/vis_builder/public/application/components/top_nav.tsx +++ b/src/plugins/vis_builder/public/application/components/top_nav.tsx @@ -14,7 +14,6 @@ import './top_nav.scss'; import { useIndexPatterns, useSavedVisBuilderVis } from '../utils/use'; import { useTypedSelector, useTypedDispatch } from '../utils/state_management'; import { setEditorState } from '../utils/state_management/metadata_slice'; -import { useCanSave } from '../utils/use/use_can_save'; import { saveStateToSavedObject } from '../../saved_visualizations/transforms'; import { TopNavMenuData } from '../../../../navigation/public'; import { opensearchFilters, connectStorageToQueryState } from '../../../../data/public'; @@ -33,7 +32,6 @@ export const TopNav = () => { const rootState = useTypedSelector((state) => state); const dispatch = useTypedDispatch(); - const saveDisabledReason = useCanSave(); const savedVisBuilderVis = useSavedVisBuilderVis(visualizationIdFromUrl); connectStorageToQueryState(services.data.query, services.osdUrlStateStorage, { filters: opensearchFilters.FilterStateStore.APP_STATE, @@ -53,7 +51,6 @@ export const TopNav = () => { { visualizationIdFromUrl, savedVisBuilderVis: saveStateToSavedObject(savedVisBuilderVis, rootState, indexPattern), - saveDisabledReason, dispatch, originatingApp, }, @@ -67,7 +64,6 @@ export const TopNav = () => { savedVisBuilderVis, services, visualizationIdFromUrl, - saveDisabledReason, dispatch, indexPattern, originatingApp, diff --git a/src/plugins/vis_builder/public/application/utils/get_top_nav_config.test.tsx b/src/plugins/vis_builder/public/application/utils/get_top_nav_config.test.tsx index 353b9d90e1ff..536596cc9e1f 100644 --- a/src/plugins/vis_builder/public/application/utils/get_top_nav_config.test.tsx +++ b/src/plugins/vis_builder/public/application/utils/get_top_nav_config.test.tsx @@ -95,7 +95,10 @@ describe('getOnSave', () => { }, ], }, - "searchSourceFields": Object {}, + "searchSourceFields": Object { + "filter": null, + "query": null, + }, "styleState": "", "title": "new title", "version": 0, diff --git a/src/plugins/vis_builder/public/application/utils/get_top_nav_config.tsx b/src/plugins/vis_builder/public/application/utils/get_top_nav_config.tsx index 2a30e1700b43..9a4388ec793e 100644 --- a/src/plugins/vis_builder/public/application/utils/get_top_nav_config.tsx +++ b/src/plugins/vis_builder/public/application/utils/get_top_nav_config.tsx @@ -41,22 +41,16 @@ import { VisBuilderSavedObject } from '../../types'; import { AppDispatch } from './state_management'; import { EDIT_PATH, VISBUILDER_SAVED_OBJECT } from '../../../common'; import { setEditorState } from './state_management/metadata_slice'; + export interface TopNavConfigParams { visualizationIdFromUrl: string; savedVisBuilderVis: VisBuilderSavedObject; - saveDisabledReason?: string; dispatch: AppDispatch; originatingApp?: string; } export const getTopNavConfig = ( - { - visualizationIdFromUrl, - savedVisBuilderVis, - saveDisabledReason, - dispatch, - originatingApp, - }: TopNavConfigParams, + { visualizationIdFromUrl, savedVisBuilderVis, dispatch, originatingApp }: TopNavConfigParams, services: VisBuilderServices ) => { const { @@ -84,8 +78,7 @@ export const getTopNavConfig = ( defaultMessage: 'save', }), testId: 'visBuilderSaveButton', - disableButton: !!saveDisabledReason, - tooltip: saveDisabledReason, + disableButton: false, run: (_anchorElement) => { const saveModal = ( { const saveOptions = { newTitle: savedVisBuilderVis.title, @@ -172,7 +164,7 @@ export const getOnSave = ( returnToOrigin: boolean; newDescription?: string; }) => { - const { embeddable, toastNotifications, application, history } = services; + const { data, embeddable, toastNotifications, application, history } = services; const stateTransfer = embeddable.getStateTransfer(); if (!savedVisBuilderVis) { @@ -183,6 +175,10 @@ export const getOnSave = ( savedVisBuilderVis.title = newTitle; savedVisBuilderVis.description = newDescription; savedVisBuilderVis.copyOnSave = newCopyOnSave; + const searchSourceInstance = savedVisBuilderVis.searchSourceFields; + searchSourceInstance.query = data.query.queryString.getQuery() || null; + searchSourceInstance.filter = data.query.filterManager.getFilters() || null; + savedVisBuilderVis.searchSourceFields = searchSourceInstance; const newlyCreated = !savedVisBuilderVis.id || savedVisBuilderVis.copyOnSave; try { diff --git a/src/plugins/vis_builder/public/application/utils/use/use_can_save.ts b/src/plugins/vis_builder/public/application/utils/use/use_can_save.ts deleted file mode 100644 index 7da320d266f3..000000000000 --- a/src/plugins/vis_builder/public/application/utils/use/use_can_save.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { i18n } from '@osd/i18n'; -import { useTypedSelector } from '../state_management'; - -export const useCanSave = () => { - const isEmpty = useTypedSelector( - (state) => state.visualization.activeVisualization?.aggConfigParams?.length === 0 - ); - const hasNoChange = useTypedSelector((state) => state.metadata.editor.state !== 'dirty'); - const hasDraftAgg = useTypedSelector( - (state) => !!state.visualization.activeVisualization?.draftAgg - ); - const errorMsg = getErrorMsg(isEmpty, hasNoChange, hasDraftAgg); - - return errorMsg; -}; - -// TODO: Need to finalize the error messages -const getErrorMsg = (isEmpty, hasNoChange, hasDraftAgg) => { - const i18nTranslate = (key: string, defaultMessage: string) => - i18n.translate(`visBuilder.saveVisualizationTooltip.${key}`, { - defaultMessage, - }); - - if (isEmpty) { - return i18nTranslate('empty', 'The canvas is empty. Add some aggregations before saving.'); - } else if (hasNoChange) { - return i18nTranslate('noChange', 'Add some changes before saving.'); - } else if (hasDraftAgg) { - return i18nTranslate( - 'hasDraftAgg', - 'Has unapplied aggregations changes, update them before saving.' - ); - } else { - return undefined; - } -}; diff --git a/src/plugins/vis_builder/public/application/utils/use/use_saved_vis_builder_vis.ts b/src/plugins/vis_builder/public/application/utils/use/use_saved_vis_builder_vis.ts index 44ffbaf75953..a8cbfb9ff6a5 100644 --- a/src/plugins/vis_builder/public/application/utils/use/use_saved_vis_builder_vis.ts +++ b/src/plugins/vis_builder/public/application/utils/use/use_saved_vis_builder_vis.ts @@ -35,6 +35,7 @@ export const useSavedVisBuilderVis = (visualizationIdFromUrl: string | undefined const { application: { navigateToApp }, chrome, + data, history, http: { basePath }, toastNotifications, @@ -61,6 +62,19 @@ export const useSavedVisBuilderVis = (visualizationIdFromUrl: string | undefined const { title, state } = getStateFromSavedObject(savedVisBuilderVis); chrome.setBreadcrumbs(getEditBreadcrumbs(title, navigateToApp)); chrome.docTitle.change(title); + // sync initial app filters from savedObject to filterManager + const filters = savedVisBuilderVis.searchSourceFields.filter; + const query = + savedVisBuilderVis.searchSourceFields.query || data.query.queryString.getDefaultQuery(); + const actualFilters = []; + if (filters !== undefined) { + const result = typeof filters === 'function' ? filters() : filters; + if (result !== undefined) { + actualFilters.push(...(Array.isArray(result) ? result : [result])); + } + } + data.query.filterManager.setAppFilters(actualFilters); + data.query.queryString.setQuery(query); dispatch(setUIStateState(state.ui)); dispatch(setStyleState(state.style)); diff --git a/src/plugins/vis_builder/public/embeddable/vis_builder_embeddable.tsx b/src/plugins/vis_builder/public/embeddable/vis_builder_embeddable.tsx index a931877ffe6d..108e117bdf41 100644 --- a/src/plugins/vis_builder/public/embeddable/vis_builder_embeddable.tsx +++ b/src/plugins/vis_builder/public/embeddable/vis_builder_embeddable.tsx @@ -35,16 +35,18 @@ import { getTypeService, getUIActions, } from '../plugin_services'; -import { PersistedState } from '../../../visualizations/public'; +import { PersistedState, prepareJson } from '../../../visualizations/public'; import { VisBuilderSavedVis } from '../saved_visualizations/transforms'; import { handleVisEvent } from '../application/utils/handle_vis_event'; import { VisBuilderEmbeddableFactoryDeps } from './vis_builder_embeddable_factory'; +import { VisBuilderSavedObject } from '../types'; // Apparently this needs to match the saved object type for the clone and replace panel actions to work export const VISBUILDER_EMBEDDABLE = VISBUILDER_SAVED_OBJECT; export interface VisBuilderEmbeddableConfiguration { savedVis: VisBuilderSavedVis; + savedObject: VisBuilderSavedObject; indexPatterns?: IIndexPattern[]; editPath: string; editUrl: string; @@ -79,6 +81,7 @@ export class VisBuilderEmbeddable extends Embeddable