diff --git a/app/client/src/components/editorComponents/ActionCreator/index.tsx b/app/client/src/components/editorComponents/ActionCreator/index.tsx index 86cf9d01dd..519fd91f73 100644 --- a/app/client/src/components/editorComponents/ActionCreator/index.tsx +++ b/app/client/src/components/editorComponents/ActionCreator/index.tsx @@ -1,40 +1,41 @@ -import React, { useMemo } from "react"; -import { AppState } from "reducers"; -import { - getActionsForCurrentPage, - getDBDatasources, -} from "selectors/entitiesSelector"; import { createActionRequest } from "actions/actionActions"; -import { - getModalDropdownList, - getNextModalName, -} from "selectors/widgetSelectors"; +import { createModalAction } from "actions/widgetActions"; +import { TreeDropdownOption } from "components/ads/TreeDropdown"; +import TreeStructure from "components/utils/TreeStructure"; +import { OnboardingStep } from "constants/OnboardingConstants"; +import { ReduxActionTypes } from "constants/ReduxActionConstants"; +import { INTEGRATION_EDITOR_URL, INTEGRATION_TABS } from "constants/routes"; +import { PluginType } from "entities/Action"; +import { Datasource } from "entities/Datasource"; +import { keyBy } from "lodash"; +import { getActionConfig } from "pages/Editor/Explorer/Actions/helpers"; +import { apiIcon, getPluginIcon } from "pages/Editor/Explorer/ExplorerIcons"; +import React, { useMemo } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { AppState } from "reducers"; +import { getCurrentStep, getCurrentSubStep } from "sagas/OnboardingSagas"; +import { getWidgetOptionsTree } from "sagas/selectors"; import { getCurrentApplicationId, getCurrentPageId, } from "selectors/editorSelectors"; -import { Datasource } from "entities/Datasource"; +import { + getActionsForCurrentPage, + getDBDatasources, + getPageListAsOptions, +} from "selectors/entitiesSelector"; +import { + getModalDropdownList, + getNextModalName, +} from "selectors/widgetSelectors"; +import { createNewQueryName } from "utils/AppsmithUtils"; +import history from "utils/history"; import Fields, { - ACTION_TRIGGER_REGEX, - ACTION_ANONYMOUS_FUNC_REGEX, ActionType, + ACTION_ANONYMOUS_FUNC_REGEX, + ACTION_TRIGGER_REGEX, FieldType, } from "./Fields"; -import { TreeDropdownOption } from "components/ads/TreeDropdown"; -import { useDispatch, useSelector } from "react-redux"; -import { createModalAction } from "actions/widgetActions"; -import { createNewQueryName } from "utils/AppsmithUtils"; -import TreeStructure from "components/utils/TreeStructure"; -import { getWidgets } from "sagas/selectors"; -import { PluginType } from "entities/Action"; -import { INTEGRATION_EDITOR_URL, INTEGRATION_TABS } from "constants/routes"; -import history from "utils/history"; -import { keyBy } from "lodash"; -import { getPluginIcon, apiIcon } from "pages/Editor/Explorer/ExplorerIcons"; -import { getActionConfig } from "pages/Editor/Explorer/Actions/helpers"; -import { getCurrentStep, getCurrentSubStep } from "sagas/OnboardingSagas"; -import { OnboardingStep } from "constants/OnboardingConstants"; -import { ReduxActionTypes } from "constants/ReduxActionConstants"; /* eslint-disable @typescript-eslint/ban-types */ /* TODO: Function and object types need to be updated to enable the lint rule */ @@ -226,14 +227,6 @@ function getFieldFromValue( return fields; } -function getPageDropdownOptions(state: AppState) { - return state.entities.pageList.pages.map((page) => ({ - label: page.pageName, - id: page.pageId, - value: `'${page.pageName}'`, - })); -} - function useModalDropdownList() { const dispatch = useDispatch(); const nextModalName = useSelector(getNextModalName); @@ -264,19 +257,6 @@ function useModalDropdownList() { return finalList; } -function useWidgetOptionTree() { - const widgets = useSelector(getWidgets) || {}; - return Object.values(widgets) - .filter((w) => w.type !== "CANVAS_WIDGET" && w.type !== "BUTTON_WIDGET") - .map((w) => { - return { - label: w.widgetName, - id: w.widgetName, - value: `"${w.widgetName}"`, - }; - }); -} - function getIntegrationOptionsWithChildren( pageId: string, plugins: any, @@ -412,9 +392,9 @@ type ActionCreatorProps = { export function ActionCreator(props: ActionCreatorProps) { const integrationOptionTree = useIntegrationsOptionTree(); - const widgetOptionTree = useWidgetOptionTree(); + const widgetOptionTree = useSelector(getWidgetOptionsTree); const modalDropdownList = useModalDropdownList(); - const pageDropdownOptions = useSelector(getPageDropdownOptions); + const pageDropdownOptions = useSelector(getPageListAsOptions); const fields = getFieldFromValue(props.value); return ( diff --git a/app/client/src/components/editorComponents/CodeEditor/index.tsx b/app/client/src/components/editorComponents/CodeEditor/index.tsx index fa07d9a7e6..2e5f455fe1 100644 --- a/app/client/src/components/editorComponents/CodeEditor/index.tsx +++ b/app/client/src/components/editorComponents/CodeEditor/index.tsx @@ -63,6 +63,7 @@ import { getEntityNameAndPropertyPath } from "workers/evaluationUtils"; import Button from "components/ads/Button"; import { getPluginIdToImageLocation } from "sagas/selectors"; import { ExpectedValueExample } from "utils/validation/common"; +import { getRecentEntityIds } from "selectors/globalSearchSelectors"; const AUTOCOMPLETE_CLOSE_KEY_CODES = [ "Enter", @@ -600,7 +601,7 @@ const mapStateToProps = (state: AppState): ReduxStateProps => ({ dynamicData: getDataTreeForAutocomplete(state), datasources: state.entities.datasources, pluginIdToImageLocation: getPluginIdToImageLocation(state), - recentEntities: state.ui.globalSearch.recentEntities.map((r) => r.id), + recentEntities: getRecentEntityIds(state), }); const mapDispatchToProps = (dispatch: any): ReduxDispatchProps => ({ diff --git a/app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.tsx b/app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.tsx index 5bf3101135..defb058cfc 100644 --- a/app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.tsx +++ b/app/client/src/pages/Editor/Explorer/Actions/ActionEntityContextMenu.tsx @@ -1,23 +1,20 @@ -import React, { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import TreeDropdown from "pages/Editor/Explorer/TreeDropdown"; - -import { AppState } from "reducers"; -import ContextMenuTrigger from "../ContextMenuTrigger"; - import { - moveActionRequest, copyActionRequest, deleteAction, + moveActionRequest, } from "actions/actionActions"; - import { initExplorerEntityNameEdit } from "actions/explorerActions"; -import { ContextMenuPopoverModifiers, ExplorerURLParams } from "../helpers"; -import { noop } from "lodash"; -import { useNewActionName } from "./helpers"; -import { useParams } from "react-router"; import { BUILDER_PAGE_URL } from "constants/routes"; +import { noop } from "lodash"; +import TreeDropdown from "pages/Editor/Explorer/TreeDropdown"; +import React, { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { useParams } from "react-router"; +import { getPageListAsOptions } from "selectors/entitiesSelector"; import history from "utils/history"; +import ContextMenuTrigger from "../ContextMenuTrigger"; +import { ContextMenuPopoverModifiers, ExplorerURLParams } from "../helpers"; +import { useNewActionName } from "./helpers"; type EntityContextMenuProps = { id: string; @@ -58,13 +55,7 @@ export function ActionEntityContextMenu(props: EntityContextMenuProps) { [dispatch], ); - const menuPages = useSelector((state: AppState) => { - return state.entities.pageList.pages.map((page) => ({ - label: page.pageName, - id: page.pageId, - value: page.pageName, - })); - }); + const menuPages = useSelector(getPageListAsOptions); const editActionName = useCallback( () => dispatch(initExplorerEntityNameEdit(props.id)), diff --git a/app/client/src/pages/Editor/Explorer/Entity/Name.tsx b/app/client/src/pages/Editor/Explorer/Entity/Name.tsx index c58b3440be..ff8b5a2bd0 100644 --- a/app/client/src/pages/Editor/Explorer/Entity/Name.tsx +++ b/app/client/src/pages/Editor/Explorer/Entity/Name.tsx @@ -1,20 +1,25 @@ -import React, { - useCallback, - useMemo, - useState, - useEffect, - forwardRef, -} from "react"; -import { useSelector, useDispatch } from "react-redux"; -import styled from "styled-components"; import EditableText, { EditInteractionKind, } from "components/editorComponents/EditableText"; -import { removeSpecialChars } from "utils/helpers"; -import { AppState } from "reducers"; -import { Page, ReduxActionTypes } from "constants/ReduxActionConstants"; import { Colors } from "constants/Colors"; +import { ReduxActionTypes } from "constants/ReduxActionConstants"; import { WidgetTypes } from "constants/WidgetConstants"; +import React, { + forwardRef, + useCallback, + useEffect, + useMemo, + useState, +} from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { AppState } from "reducers"; +import { + getExistingActionNames, + getExistingPageNames, + getExistingWidgetNames, +} from "selectors/entitiesSelector"; +import styled from "styled-components"; +import { removeSpecialChars } from "utils/helpers"; const searchHighlightSpanClassName = "token"; const searchTokenizationDelimiter = "!!"; @@ -100,22 +105,12 @@ export const EntityName = forwardRef( setUpdatedName(name); }, [name, nameUpdateError]); - const existingPageNames: string[] = useSelector((state: AppState) => - state.entities.pageList.pages.map((page: Page) => page.pageName), - ); + const existingPageNames: string[] = useSelector(getExistingPageNames); + const existingWidgetNames: string[] = useSelector(getExistingWidgetNames); - const existingWidgetNames: string[] = useSelector((state: AppState) => - Object.values(state.entities.canvasWidgets).map( - (widget) => widget.widgetName, - ), - ); const dispatch = useDispatch(); - const existingActionNames: string[] = useSelector((state: AppState) => - state.entities.actions.map( - (action: { config: { name: string } }) => action.config.name, - ), - ); + const existingActionNames: string[] = useSelector(getExistingActionNames); const hasNameConflict = useCallback( ( diff --git a/app/client/src/sagas/selectors.tsx b/app/client/src/sagas/selectors.tsx index 82559b7bab..ac3a4d57ee 100644 --- a/app/client/src/sagas/selectors.tsx +++ b/app/client/src/sagas/selectors.tsx @@ -29,6 +29,18 @@ export const getWidgetIdsByType = (state: AppState, type: WidgetType) => { .map((widget: FlattenedWidgetProps) => widget.widgetId); }; +export const getWidgetOptionsTree = createSelector(getWidgets, (widgets) => + Object.values(widgets) + .filter((w) => w.type !== "CANVAS_WIDGET" && w.type !== "BUTTON_WIDGET") + .map((w) => { + return { + label: w.widgetName, + id: w.widgetName, + value: `"${w.widgetName}"`, + }; + }), +); + export const getEditorConfigs = ( state: AppState, ): { pageId: string; layoutId: string } | undefined => { diff --git a/app/client/src/selectors/entitiesSelector.ts b/app/client/src/selectors/entitiesSelector.ts index da5fee0f85..2ec41d031c 100644 --- a/app/client/src/selectors/entitiesSelector.ts +++ b/app/client/src/selectors/entitiesSelector.ts @@ -403,4 +403,30 @@ export const getAllPageWidgets = createSelector( }, ); +export const getPageListAsOptions = createSelector( + (state: AppState) => state.entities.pageList.pages, + (pages) => + pages.map((page) => ({ + label: page.pageName, + id: page.pageId, + value: `'${page.pageName}'`, + })), +); + +export const getExistingPageNames = createSelector( + (state: AppState) => state.entities.pageList.pages, + (pages) => pages.map((page) => page.pageName), +); + +export const getExistingWidgetNames = createSelector( + (state: AppState) => state.entities.canvasWidgets, + (widgets) => Object.values(widgets).map((widget) => widget.pageName), +); + +export const getExistingActionNames = createSelector( + (state: AppState) => state.entities.actions, + (actions) => + actions.map((action: { config: { name: string } }) => action.config.name), +); + export const getAppMode = (state: AppState) => state.entities.app.mode; diff --git a/app/client/src/selectors/globalSearchSelectors.tsx b/app/client/src/selectors/globalSearchSelectors.tsx new file mode 100644 index 0000000000..ae9e4db1fe --- /dev/null +++ b/app/client/src/selectors/globalSearchSelectors.tsx @@ -0,0 +1,14 @@ +import { createSelector } from "reselect"; + +import { AppState } from "reducers"; +import { RecentEntity } from "components/editorComponents/GlobalSearch/utils"; + +export const getRecentEntities = (state: AppState) => + state.ui.globalSearch.recentEntities; + +export const getRecentEntityIds = createSelector( + getRecentEntities, + (entities: RecentEntity[]) => { + return entities.map((r) => r.id); + }, +);