From 1f2cb35b16a5356e65f6b435828497d63f3132f9 Mon Sep 17 00:00:00 2001
From: Kawika Avilla <kavilla414@gmail.com>
Date: Mon, 18 Mar 2024 18:52:42 -0700
Subject: [PATCH] [Discover] options button in canvas to toggle legacy mode
 (#6170)

* [Discover] options button in canvas to toggle legacy mode

Removes top nav bar link and provides a button option.

Issue:
n/a

Signed-off-by: Kawika Avilla <kavilla414@gmail.com>
---
 .../components/top_nav/get_top_nav_links.tsx  | 57 -------------------
 .../components/utils/local_storage.ts         |  4 +-
 .../canvas/discover_canvas.scss               |  7 +++
 .../view_components/canvas/index.tsx          | 50 +++++++++++++++-
 .../apps/dashboard/dashboard_filter_bar.js    |  1 +
 .../apps/dashboard/dashboard_filtering.js     |  1 +
 .../apps/dashboard/dashboard_state.js         |  1 +
 .../apps/management/_scripted_fields.js       |  8 +--
 test/functional/page_objects/discover_page.ts | 11 ++--
 .../test_suites/doc_views/doc_views.ts        |  2 +-
 10 files changed, 72 insertions(+), 70 deletions(-)

diff --git a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx
index 1b20c444e860..6760416ab8c9 100644
--- a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx
+++ b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx
@@ -5,7 +5,6 @@
 
 import { i18n } from '@osd/i18n';
 import React from 'react';
-import { EuiText } from '@elastic/eui';
 import { DiscoverViewServices } from '../../../build_services';
 import { SavedSearch } from '../../../saved_searches';
 import { Adapters } from '../../../../../inspector/public';
@@ -25,7 +24,6 @@ import { DOC_HIDE_TIME_COLUMN_SETTING, SORT_DEFAULT_ORDER_SETTING } from '../../
 import { getSortForSearchSource } from '../../view_components/utils/get_sort_for_search_source';
 import { getRootBreadcrumbs } from '../../helpers/breadcrumbs';
 import { syncQueryStateWithUrl } from '../../../../../data/public';
-import { getNewDiscoverSetting, setNewDiscoverSetting } from '../utils/local_storage';
 import { OpenSearchPanel } from './open_search_panel';
 
 export const getTopNavLinks = (
@@ -44,7 +42,6 @@ export const getTopNavLinks = (
     store,
     data: { query },
     osdUrlStateStorage,
-    storage,
   } = services;
 
   const newSearch = {
@@ -234,61 +231,7 @@ export const getTopNavLinks = (
     },
   };
 
-  const newDiscoverButtonLabel = i18n.translate('discover.localMenu.discoverButton.label.new', {
-    defaultMessage: 'Try new Discover',
-  });
-  const oldDiscoverButtonLabel = i18n.translate('discover.localMenu.discoverButton.label.old', {
-    defaultMessage: 'Use legacy Discover',
-  });
-  const isNewDiscover = getNewDiscoverSetting(storage);
-  const newTable: TopNavMenuData = {
-    id: 'table-datagrid',
-    label: isNewDiscover ? oldDiscoverButtonLabel : newDiscoverButtonLabel,
-    description: i18n.translate('discover.localMenu.newTableDescription', {
-      defaultMessage: 'New Discover toggle Experience',
-    }),
-    testId: 'datagridTableButton',
-    run: async () => {
-      // Read the current state from localStorage
-      const newDiscoverEnabled = getNewDiscoverSetting(storage);
-      if (newDiscoverEnabled) {
-        const confirmed = await services.overlays.openConfirm(
-          toMountPoint(
-            <EuiText>
-              <p>
-                Help drive future improvements by{' '}
-                <a href="https://survey.opensearch.org" target="_blank" rel="noopener noreferrer">
-                  providing feedback
-                </a>{' '}
-                about your experience.
-              </p>
-            </EuiText>
-          ),
-          {
-            title: i18n.translate('discover.localMenu.newTableConfirmModalTitle', {
-              defaultMessage: 'Share your thoughts on the latest Discover features',
-            }),
-            cancelButtonText: 'Cancel',
-            confirmButtonText: 'Turn off new features',
-            defaultFocusedButton: 'confirm',
-          }
-        );
-
-        if (confirmed) {
-          setNewDiscoverSetting(false, storage);
-          window.location.reload();
-        }
-      } else {
-        // Save the new setting to localStorage
-        setNewDiscoverSetting(true, storage);
-        window.location.reload();
-      }
-    },
-    iconType: isNewDiscover ? 'editorUndo' : 'cheer',
-  };
-
   return [
-    newTable,
     newSearch,
     ...(capabilities.discover?.save ? [saveSearch] : []),
     openSearch,
diff --git a/src/plugins/discover/public/application/components/utils/local_storage.ts b/src/plugins/discover/public/application/components/utils/local_storage.ts
index 5e812de8e97d..68bba0aafc99 100644
--- a/src/plugins/discover/public/application/components/utils/local_storage.ts
+++ b/src/plugins/discover/public/application/components/utils/local_storage.ts
@@ -9,9 +9,9 @@ export const NEW_DISCOVER_KEY = 'discover:newExpereince';
 
 export const getNewDiscoverSetting = (storage: Storage): boolean => {
   const storedValue = storage.get(NEW_DISCOVER_KEY);
-  return storedValue !== null ? JSON.parse(storedValue) : false;
+  return storedValue !== null ? storedValue : false;
 };
 
 export const setNewDiscoverSetting = (value: boolean, storage: Storage) => {
-  storage.set(NEW_DISCOVER_KEY, JSON.stringify(value));
+  storage.set(NEW_DISCOVER_KEY, value);
 };
diff --git a/src/plugins/discover/public/application/view_components/canvas/discover_canvas.scss b/src/plugins/discover/public/application/view_components/canvas/discover_canvas.scss
index 36408bd88366..2c2c8dfe8ebb 100644
--- a/src/plugins/discover/public/application/view_components/canvas/discover_canvas.scss
+++ b/src/plugins/discover/public/application/view_components/canvas/discover_canvas.scss
@@ -9,6 +9,13 @@
 
   &_results {
     margin-left: $euiSizeM;
+    position: relative;
+  }
+
+  &_options {
+    position: absolute;
+    top: 0;
+    right: 0;
   }
 }
 
diff --git a/src/plugins/discover/public/application/view_components/canvas/index.tsx b/src/plugins/discover/public/application/view_components/canvas/index.tsx
index 1c2681995f98..ab34878750a7 100644
--- a/src/plugins/discover/public/application/view_components/canvas/index.tsx
+++ b/src/plugins/discover/public/application/view_components/canvas/index.tsx
@@ -4,7 +4,7 @@
  */
 
 import React, { useEffect, useState, useRef, useCallback } from 'react';
-import { EuiPanel } from '@elastic/eui';
+import { EuiButtonIcon, EuiContextMenu, EuiPanel, EuiPopover, EuiSwitch } from '@elastic/eui';
 import { TopNav } from './top_nav';
 import { ViewProps } from '../../../../../data_explorer/public';
 import { DiscoverTable } from './discover_table';
@@ -21,13 +21,14 @@ import { filterColumns } from '../utils/filter_columns';
 import { DEFAULT_COLUMNS_SETTING, MODIFY_COLUMNS_ON_SWITCH } from '../../../../common';
 import { OpenSearchSearchHit } from '../../../application/doc_views/doc_views_types';
 import './discover_canvas.scss';
+import { getNewDiscoverSetting, setNewDiscoverSetting } from '../../components/utils/local_storage';
 
 // eslint-disable-next-line import/no-default-export
 export default function DiscoverCanvas({ setHeaderActionMenu, history }: ViewProps) {
   const panelRef = useRef<HTMLDivElement>(null);
   const { data$, refetch$, indexPattern } = useDiscoverContext();
   const {
-    services: { uiSettings },
+    services: { uiSettings, storage },
   } = useOpenSearchDashboards<DiscoverViewServices>();
   const { columns } = useSelector((state) => state.discover);
   const filteredColumns = filterColumns(
@@ -96,6 +97,50 @@ export default function DiscoverCanvas({ setHeaderActionMenu, history }: ViewPro
     }
   };
 
+  const [isOptionsOpen, setOptionsOpen] = useState(false);
+  const [useLegacy, setUseLegacy] = useState(!getNewDiscoverSetting(storage));
+  const DiscoverOptions = () => (
+    <EuiPopover
+      button={
+        <EuiButtonIcon
+          data-test-subj="discoverOptionsButton"
+          size="s"
+          iconType="gear"
+          onClick={() => setOptionsOpen(!isOptionsOpen)}
+        />
+      }
+      closePopover={() => setOptionsOpen(false)}
+      isOpen={isOptionsOpen}
+      panelPaddingSize="none"
+      className="dscCanvas_options"
+    >
+      <EuiContextMenu
+        initialPanelId={0}
+        panels={[
+          {
+            id: 0,
+            title: 'Options',
+            content: (
+              <EuiPanel>
+                <EuiSwitch
+                  label="Enable legacy Discover"
+                  checked={useLegacy}
+                  data-test-subj="discoverOptionsLegacySwitch"
+                  onChange={(e) => {
+                    const checked = e.target.checked;
+                    setUseLegacy(checked);
+                    setNewDiscoverSetting(!checked, storage);
+                    window.location.reload();
+                  }}
+                />
+              </EuiPanel>
+            ),
+          },
+        ]}
+      />
+    </EuiPopover>
+  );
+
   return (
     <EuiPanel
       panelRef={panelRef}
@@ -122,6 +167,7 @@ export default function DiscoverCanvas({ setHeaderActionMenu, history }: ViewPro
         <EuiPanel hasShadow={false} paddingSize="none" className="dscCanvas_results">
           <MemoizedDiscoverChartContainer {...fetchState} />
           <MemoizedDiscoverTable rows={rows} scrollToTop={scrollToTop} />
+          <DiscoverOptions />
         </EuiPanel>
       )}
     </EuiPanel>
diff --git a/test/functional/apps/dashboard/dashboard_filter_bar.js b/test/functional/apps/dashboard/dashboard_filter_bar.js
index dde86c697e3c..17e29fa5cf6f 100644
--- a/test/functional/apps/dashboard/dashboard_filter_bar.js
+++ b/test/functional/apps/dashboard/dashboard_filter_bar.js
@@ -193,6 +193,7 @@ export default function ({ getService, getPageObjects }) {
       before(async () => {
         await filterBar.ensureFieldEditorModalIsClosed();
         await PageObjects.common.navigateToApp('discover');
+        await PageObjects.timePicker.setDefaultDataRange();
         await PageObjects.discover.switchDiscoverTable('new');
         await PageObjects.common.navigateToApp('dashboard');
         await PageObjects.dashboard.gotoDashboardLandingPage();
diff --git a/test/functional/apps/dashboard/dashboard_filtering.js b/test/functional/apps/dashboard/dashboard_filtering.js
index 1040b87f6168..6be4b4837da0 100644
--- a/test/functional/apps/dashboard/dashboard_filtering.js
+++ b/test/functional/apps/dashboard/dashboard_filtering.js
@@ -80,6 +80,7 @@ export default function ({ getService, getPageObjects }) {
     describe('adding a filter that excludes all data', () => {
       before(async () => {
         await PageObjects.common.navigateToApp('discover');
+        await PageObjects.timePicker.setDefaultDataRange();
         await PageObjects.discover.switchDiscoverTable('new');
         await PageObjects.common.navigateToApp('dashboard');
         await PageObjects.dashboard.gotoDashboardLandingPage();
diff --git a/test/functional/apps/dashboard/dashboard_state.js b/test/functional/apps/dashboard/dashboard_state.js
index 11196a1b69b9..78f0cdb16184 100644
--- a/test/functional/apps/dashboard/dashboard_state.js
+++ b/test/functional/apps/dashboard/dashboard_state.js
@@ -57,6 +57,7 @@ export default function ({ getService, getPageObjects }) {
   describe('dashboard state', function describeIndexTests() {
     before(async function () {
       await PageObjects.common.navigateToApp('discover');
+      await PageObjects.timePicker.setHistoricalDataRange();
       await PageObjects.discover.switchDiscoverTable('new');
       await PageObjects.common.navigateToApp('dashboard');
       await PageObjects.dashboard.initTests();
diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js
index 8a4659630ee1..f3d89138eb77 100644
--- a/test/functional/apps/management/_scripted_fields.js
+++ b/test/functional/apps/management/_scripted_fields.js
@@ -161,9 +161,9 @@ export default function ({ getService, getPageObjects }) {
         const fromTime = 'Sep 17, 2015 @ 06:31:44.000';
         const toTime = 'Sep 18, 2015 @ 18:31:44.000';
         await PageObjects.common.navigateToApp('discover');
-        await PageObjects.discover.switchDiscoverTable('new');
         await PageObjects.discover.selectIndexPattern('logstash-*');
         await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
+        await PageObjects.discover.switchDiscoverTable('new');
 
         await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName);
         await retry.try(async function () {
@@ -280,9 +280,9 @@ export default function ({ getService, getPageObjects }) {
         const fromTime = 'Sep 17, 2015 @ 06:31:44.000';
         const toTime = 'Sep 18, 2015 @ 18:31:44.000';
         await PageObjects.common.navigateToApp('discover');
-        await PageObjects.discover.switchDiscoverTable('new');
         await PageObjects.discover.selectIndexPattern('logstash-*');
         await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
+        await PageObjects.discover.switchDiscoverTable('new');
 
         await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
         await retry.try(async function () {
@@ -377,9 +377,9 @@ export default function ({ getService, getPageObjects }) {
         const fromTime = 'Sep 17, 2015 @ 06:31:44.000';
         const toTime = 'Sep 18, 2015 @ 18:31:44.000';
         await PageObjects.common.navigateToApp('discover');
-        await PageObjects.discover.switchDiscoverTable('new');
         await PageObjects.discover.selectIndexPattern('logstash-*');
         await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
+        await PageObjects.discover.switchDiscoverTable('new');
 
         await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
         await retry.try(async function () {
@@ -477,9 +477,9 @@ export default function ({ getService, getPageObjects }) {
         const fromTime = 'Sep 17, 2015 @ 19:22:00.000';
         const toTime = 'Sep 18, 2015 @ 07:00:00.000';
         await PageObjects.common.navigateToApp('discover');
-        await PageObjects.discover.switchDiscoverTable('new');
         await PageObjects.discover.selectIndexPattern('logstash-*');
         await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
+        await PageObjects.discover.switchDiscoverTable('new');
 
         await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
         await retry.try(async function () {
diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts
index cf0b03022ab9..8f03ae20ddf7 100644
--- a/test/functional/page_objects/discover_page.ts
+++ b/test/functional/page_objects/discover_page.ts
@@ -519,12 +519,15 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider
 
     public async switchDiscoverTable(tableType: string) {
       await retry.try(async () => {
-        const switchButton = await testSubjects.find('datagridTableButton');
-        const buttonText = await switchButton.getVisibleText();
+        const optionsButton = await testSubjects.find('discoverOptionsButton');
+        await optionsButton.click();
 
-        if (tableType === 'new' && buttonText.includes('Try new Discover')) {
+        const switchButton = await testSubjects.find('discoverOptionsLegacySwitch');
+        const isLegacyChecked = (await switchButton.getAttribute('aria-checked')) === 'true';
+
+        if (tableType === 'new' && isLegacyChecked) {
           await switchButton.click();
-        } else if (tableType === 'legacy' && buttonText.includes('Use legacy Discover')) {
+        } else if (tableType === 'legacy' && !isLegacyChecked) {
           await switchButton.click();
         }
       });
diff --git a/test/plugin_functional/test_suites/doc_views/doc_views.ts b/test/plugin_functional/test_suites/doc_views/doc_views.ts
index b745d6e8a417..d215017132ae 100644
--- a/test/plugin_functional/test_suites/doc_views/doc_views.ts
+++ b/test/plugin_functional/test_suites/doc_views/doc_views.ts
@@ -39,10 +39,10 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
   describe('custom doc views with datagrid table', function () {
     before(async () => {
       await PageObjects.common.navigateToApp('discover');
-      await PageObjects.discover.switchDiscoverTable('new');
       // TODO: change back to setDefaultRange() once we resolve
       // https://github.com/opensearch-project/OpenSearch-Dashboards/issues/5241
       await PageObjects.timePicker.setDefaultRangeForDiscover();
+      await PageObjects.discover.switchDiscoverTable('new');
     });
 
     it('should show custom doc views', async () => {