From 3408729df9f4239f957a65738ec948cc28aa395b Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Wed, 26 Apr 2023 21:33:13 +0530 Subject: [PATCH 01/72] feat: Open doc links in a new tab (#22613) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description When user clicks on a docs link, open the docs in a new tab instead of the omnibar. Fixes #22409 Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video ## Type of change - New feature (non-breaking change which adds functionality) ## How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Provide instructions, so we can reproduce. > Please also list any relevant details for your test configuration. > Delete anything that is not important - Manual - Jest - Cypress ### Test Plan > Add Testsmith test cases links that relate to this PR ### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) ## Checklist: ### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag ### QA activity: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test --- .../OtherUIFeatures/Omnibar_spec.js | 9 +++-- .../ApiTests/API_ContextMenu_spec.js | 8 ++--- .../ServerSideTests/QueryPane/DSDocs_Spec.ts | 24 +++++-------- .../cypress/support/Pages/AggregateHelper.ts | 12 +++++++ .../src/constants/DocumentationLinks.ts | 28 +++++++++++++++ .../Editor/APIEditor/CommonEditorForm.tsx | 18 ++++------ .../pages/Editor/DataSourceEditor/DBForm.tsx | 11 +++--- .../pages/Editor/DataSourceEditor/index.tsx | 9 ----- .../Editor/PropertyPane/ConnectDataCTA.tsx | 19 +++------- .../Editor/QueryEditor/EditorJSONtoForm.tsx | 35 ++++++++----------- app/client/src/utils/AnalyticsUtil.tsx | 3 +- 11 files changed, 88 insertions(+), 88 deletions(-) create mode 100644 app/client/src/constants/DocumentationLinks.ts diff --git a/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/OtherUIFeatures/Omnibar_spec.js b/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/OtherUIFeatures/Omnibar_spec.js index 99c5576784..2747f7219a 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/OtherUIFeatures/Omnibar_spec.js +++ b/app/client/cypress/integration/Regression_TestSuite/ClientSideTests/OtherUIFeatures/Omnibar_spec.js @@ -13,12 +13,11 @@ describe("Omnibar functionality test cases", () => { cy.addDsl(dsl); }); - it("1. Bug #15104 The Data is not displayed in Omnibar after clicking on learn more link from property pane", function () { + it("1. Docs tab opens after clicking on learn more link from property pane", function () { cy.dragAndDropToCanvas("audiowidget", { x: 300, y: 500 }); - cy.xpath('//span[text()="Learn more"]').click(); - cy.get(locators._omnibarDescription).scrollTo("top"); - cy.get(omnibar.openDocumentationLink); - cy.get("body").click(0, 0); + ObjectsRegistry.AggregateHelper.AssertNewTabOpened(() => { + cy.xpath('//span[text()="Learn more"]').click(); + }); }); it("2.Verify omnibar is present across all pages and validate its fields", function () { diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/ApiTests/API_ContextMenu_spec.js b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/ApiTests/API_ContextMenu_spec.js index 265fab56c8..4554991262 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/ApiTests/API_ContextMenu_spec.js +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/ApiTests/API_ContextMenu_spec.js @@ -15,10 +15,10 @@ describe("API Panel Test Functionality ", function () { cy.get("body").click(0, 0); ee.ExpandCollapseEntity("Queries/JS"); ee.ActionContextMenuByEntityName("FirstAPI", "Copy to page", "SecondPage"); - // click on learn how link - cy.get(".t--learn-how-apis-link").click(); - // this should open in a global search modal - cy.get(commonlocators.globalSearchModal); + ObjectsRegistry.AggregateHelper.AssertNewTabOpened(() => { + // click on learn how link + cy.get(".t--learn-how-apis-link").click(); + }); cy.get("body").click(0, 0); ee.ActionContextMenuByEntityName("FirstAPICopy", "Move to page", "Page1"); cy.wait(2000); diff --git a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/DSDocs_Spec.ts b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/DSDocs_Spec.ts index cfc96ca4ec..74be9ed0e9 100644 --- a/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/DSDocs_Spec.ts +++ b/app/client/cypress/integration/Regression_TestSuite/ServerSideTests/QueryPane/DSDocs_Spec.ts @@ -8,11 +8,9 @@ describe("Check datasource doc links", function () { cy.get("@dsName").then(($dsName) => { dsName = $dsName; _.dataSources.CreateQueryAfterDSSaved(); - _.agHelper.GetNClick(_.dataSources._queryDoc); - _.agHelper.AssertElementVisible(_.dataSources._globalSearchModal); - _.agHelper.AssertElementVisible( - _.dataSources._globalSearchInput("PostgreSQL"), - ); + _.agHelper.AssertNewTabOpened(() => { + _.agHelper.GetNClick(_.dataSources._queryDoc); + }); }); }); @@ -21,11 +19,9 @@ describe("Check datasource doc links", function () { cy.get("@dsName").then(($dsName) => { dsName = $dsName; _.dataSources.CreateQueryAfterDSSaved(); - _.agHelper.GetNClick(_.dataSources._queryDoc); - _.agHelper.AssertElementVisible(_.dataSources._globalSearchModal); - _.agHelper.AssertElementVisible( - _.dataSources._globalSearchInput("MongoDB"), - ); + _.agHelper.AssertNewTabOpened(() => { + _.agHelper.GetNClick(_.dataSources._queryDoc); + }); }); }); @@ -34,11 +30,9 @@ describe("Check datasource doc links", function () { cy.get("@dsName").then(($dsName) => { dsName = $dsName; _.dataSources.CreateQueryAfterDSSaved(); - _.agHelper.GetNClick(_.dataSources._queryDoc); - _.agHelper.AssertElementVisible(_.dataSources._globalSearchModal); - _.agHelper.AssertElementVisible( - _.dataSources._globalSearchInput("MySQL"), - ); + _.agHelper.AssertNewTabOpened(() => { + _.agHelper.GetNClick(_.dataSources._queryDoc); + }); }); }); diff --git a/app/client/cypress/support/Pages/AggregateHelper.ts b/app/client/cypress/support/Pages/AggregateHelper.ts index 6c03297708..f45fdbe39f 100644 --- a/app/client/cypress/support/Pages/AggregateHelper.ts +++ b/app/client/cypress/support/Pages/AggregateHelper.ts @@ -1169,6 +1169,18 @@ export class AggregateHelper { } } + public AssertNewTabOpened(openTabFunc: () => void) { + cy.window().then((win) => { + cy.spy(win, "open").as("windowOpen"); + openTabFunc(); + cy.get("@windowOpen").should( + "be.calledWith", + Cypress.sinon.match.string, + "_blank", + ); + }); + } + //Not used: // private xPathToCss(xpath: string) { // return xpath diff --git a/app/client/src/constants/DocumentationLinks.ts b/app/client/src/constants/DocumentationLinks.ts new file mode 100644 index 0000000000..e136825edc --- /dev/null +++ b/app/client/src/constants/DocumentationLinks.ts @@ -0,0 +1,28 @@ +import AnalyticsUtil from "../utils/AnalyticsUtil"; + +export enum DocsLink { + CAPTURE_DATA = "CAPTURE_DATA", + WHITELIST_IP = "WHITELIST_IP", + CONNECT_DATA = "CONNECT_DATA", + QUERY = "QUERY", +} + +const LinkData: Record = { + CONNECT_DATA: + "https://docs.appsmith.com/core-concepts/connecting-to-data-sources", + QUERY: + "https://docs.appsmith.com/core-concepts/connecting-to-data-sources#docusaurus_skipToContent_fallback", + WHITELIST_IP: + "https://docs.appsmith.com/core-concepts/connecting-to-data-sources/connecting-to-databases", + CAPTURE_DATA: + "https://docs.appsmith.com/core-concepts/data-access-and-binding/capturing-data-write", +}; + +export const openDoc = (type: DocsLink, link?: string, subType?: string) => { + let linkToOpen = LinkData[type]; + if (link && link.length) { + linkToOpen = link; + } + AnalyticsUtil.logEvent("OPEN_DOCS", { source: type, queryType: subType }); + window.open(linkToOpen, "_blank"); +}; diff --git a/app/client/src/pages/Editor/APIEditor/CommonEditorForm.tsx b/app/client/src/pages/Editor/APIEditor/CommonEditorForm.tsx index 5fcf72bdd7..7f5f796aa4 100644 --- a/app/client/src/pages/Editor/APIEditor/CommonEditorForm.tsx +++ b/app/client/src/pages/Editor/APIEditor/CommonEditorForm.tsx @@ -1,8 +1,8 @@ import React, { useCallback, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { - HTTP_METHOD_OPTIONS, API_EDITOR_TABS, + HTTP_METHOD_OPTIONS, } from "constants/ApiEditorConstants/CommonApiConstants"; import { GRAPHQL_HTTP_METHOD_OPTIONS } from "constants/ApiEditorConstants/GraphQLEditorConstants"; import styled from "styled-components"; @@ -11,10 +11,6 @@ import FormRow from "components/editorComponents/FormRow"; import type { PaginationField, SuggestedWidget } from "api/ActionAPI"; import type { Action, PaginationType } from "entities/Action"; import { isGraphqlPlugin, SlashCommand } from "entities/Action"; -import { - setGlobalSearchQuery, - toggleShowGlobalSearchModal, -} from "actions/globalSearchActions"; import KeyValueFieldArray from "components/editorComponents/form/fields/KeyValueFieldArray"; import ApiResponseView from "components/editorComponents/ApiResponseView"; import EmbeddedDatasourcePathField from "components/editorComponents/form/fields/EmbeddedDatasourcePathField"; @@ -48,7 +44,6 @@ import { createMessage, WIDGET_BIND_HELP, } from "@appsmith/constants/messages"; -import AnalyticsUtil from "utils/AnalyticsUtil"; import CloseEditor from "components/editorComponents/CloseEditor"; import { useParams } from "react-router"; import DataSourceList from "./ApiRightPane"; @@ -67,11 +62,14 @@ import { hasExecuteActionPermission, hasManageActionPermission, } from "@appsmith/utils/permissionHelpers"; -import { executeCommandAction } from "actions/apiPaneActions"; +import { + executeCommandAction, + setApiPaneConfigSelectedTabIndex, +} from "actions/apiPaneActions"; import { getApiPaneConfigSelectedTabIndex } from "selectors/apiPaneSelectors"; -import { setApiPaneConfigSelectedTabIndex } from "actions/apiPaneActions"; import type { AutoGeneratedHeader } from "./helpers"; import { showDebuggerFlag } from "selectors/debuggerSelectors"; +import { DocsLink, openDoc } from "../../../constants/DocumentationLinks"; const Form = styled.form` position: relative; @@ -706,9 +704,7 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) { const theme = EditorTheme.LIGHT; const handleClickLearnHow = (e: React.MouseEvent) => { e.stopPropagation(); - dispatch(setGlobalSearchQuery("capturing data")); - dispatch(toggleShowGlobalSearchModal()); - AnalyticsUtil.logEvent("OPEN_OMNIBAR", { source: "LEARN_HOW_DATASOURCE" }); + openDoc(DocsLink.CAPTURE_DATA); }; function handleSearchSnippetClick() { diff --git a/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx b/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx index 095c136c59..659cfe756b 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx @@ -13,7 +13,6 @@ import type { InjectedFormProps } from "redux-form"; import { reduxForm } from "redux-form"; import { APPSMITH_IP_ADDRESSES } from "constants/DatasourceEditorConstants"; import { getAppsmithConfigs } from "@appsmith/configs"; -import AnalyticsUtil from "utils/AnalyticsUtil"; import { convertArrayToSentence } from "utils/helpers"; import { PluginType } from "entities/Action"; import type { AppState } from "@appsmith/reducers"; @@ -35,12 +34,12 @@ import Debugger, { } from "./Debugger"; import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; import { showDebuggerFlag } from "selectors/debuggerSelectors"; +import { DocsLink, openDoc } from "../../../constants/DocumentationLinks"; const { cloudHosting } = getAppsmithConfigs(); interface DatasourceDBEditorProps extends JSONtoFormProps { setDatasourceViewMode: (viewMode: boolean) => void; - openOmnibarReadMore: (text: string) => void; datasourceId: string; applicationId: string; pageId: string; @@ -101,10 +100,8 @@ class DatasourceDBEditor extends JSONtoForm { }); }; - openOmnibarReadMore = () => { - const { openOmnibarReadMore } = this.props; - openOmnibarReadMore("connect to databases"); - AnalyticsUtil.logEvent("OPEN_OMNIBAR", { source: "READ_MORE_DATASOURCE" }); + openDocumentation = () => { + openDoc(DocsLink.WHITELIST_IP); }; render() { @@ -188,7 +185,7 @@ class DatasourceDBEditor extends JSONtoForm { {`Whitelist the IP ${convertArrayToSentence( APPSMITH_IP_ADDRESSES, )} on your database instance to connect to it. `} - + {"Learn more "} diff --git a/app/client/src/pages/Editor/DataSourceEditor/index.tsx b/app/client/src/pages/Editor/DataSourceEditor/index.tsx index 2dbe8921fe..8fdc615e6e 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/index.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/index.tsx @@ -28,8 +28,6 @@ import RestAPIDatasourceForm from "./RestAPIDatasourceForm"; import type { Datasource } from "entities/Datasource"; import type { RouteComponentProps } from "react-router"; import EntityNotFoundPane from "pages/Editor/EntityNotFoundPane"; -import { setGlobalSearchQuery } from "actions/globalSearchActions"; -import { toggleShowGlobalSearchModal } from "actions/globalSearchActions"; import { DatasourceComponentTypes } from "api/PluginApi"; import DatasourceSaasForm from "../SaaSEditor/DatasourceForm"; @@ -166,7 +164,6 @@ class DataSourceEditor extends React.Component { isNewDatasource, isSaving, isTesting, - openOmnibarReadMore, pageId, pluginId, pluginImages, @@ -189,7 +186,6 @@ class DataSourceEditor extends React.Component { isNewDatasource={isNewDatasource} isSaving={isSaving} isTesting={isTesting} - openOmnibarReadMore={openOmnibarReadMore} pageId={pageId} pluginImage={pluginImages[pluginId]} pluginType={pluginType} @@ -203,7 +199,6 @@ class DataSourceEditor extends React.Component { export interface DatasourcePaneFunctions { switchDatasource: (id: string) => void; setDatasourceViewMode: (viewMode: boolean) => void; - openOmnibarReadMore: (text: string) => void; discardTempDatasource: () => void; deleteTempDSFromDraft: () => void; toggleSaveActionFlag: (flag: boolean) => void; @@ -542,10 +537,6 @@ const mapDispatchToProps = ( }, setDatasourceViewMode: (viewMode: boolean) => dispatch(setDatasourceViewMode(viewMode)), - openOmnibarReadMore: (text: string) => { - dispatch(setGlobalSearchQuery(text)); - dispatch(toggleShowGlobalSearchModal()); - }, discardTempDatasource: () => dispatch(removeTempDatasource()), deleteTempDSFromDraft: () => dispatch(deleteTempDSFromDraft()), toggleSaveActionFlag: (flag) => dispatch(toggleSaveActionFlag(flag)), diff --git a/app/client/src/pages/Editor/PropertyPane/ConnectDataCTA.tsx b/app/client/src/pages/Editor/PropertyPane/ConnectDataCTA.tsx index d603c06726..bdf23fc4d8 100644 --- a/app/client/src/pages/Editor/PropertyPane/ConnectDataCTA.tsx +++ b/app/client/src/pages/Editor/PropertyPane/ConnectDataCTA.tsx @@ -1,18 +1,15 @@ -import React, { useCallback } from "react"; +import React from "react"; import { Button, Category, getTypographyByKey, Size } from "design-system-old"; import type { AppState } from "@appsmith/reducers"; import styled from "styled-components"; -import { useDispatch, useSelector } from "react-redux"; +import { useSelector } from "react-redux"; import { INTEGRATION_EDITOR_MODES, INTEGRATION_TABS } from "constants/routes"; import history from "utils/history"; -import { - setGlobalSearchQuery, - toggleShowGlobalSearchModal, -} from "actions/globalSearchActions"; import AnalyticsUtil from "utils/AnalyticsUtil"; import type { WidgetType } from "constants/WidgetConstants"; import { integrationEditorURL } from "RouteBuilder"; import { getCurrentPageId } from "selectors/editorSelectors"; +import { DocsLink, openDoc } from "../../../constants/DocumentationLinks"; const StyledDiv = styled.div` color: ${(props) => props.theme.colors.propertyPane.ctaTextColor}; @@ -54,15 +51,7 @@ type ConnectDataCTAProps = { }; function ConnectDataCTA(props: ConnectDataCTAProps) { - const dispatch = useDispatch(); const pageId: string = useSelector(getCurrentPageId); - const openHelpModal = useCallback(() => { - dispatch(setGlobalSearchQuery("Connecting to Data Sources")); - dispatch(toggleShowGlobalSearchModal()); - AnalyticsUtil.logEvent("OPEN_OMNIBAR", { - source: "PROPERTY_PANE_CONNECT_DATA", - }); - }, []); const onClick = () => { const { widgetId, widgetTitle, widgetType } = props; @@ -93,7 +82,7 @@ function ConnectDataCTA(props: ConnectDataCTAProps) { />