fix: side by side blank state, tooltip, and add button UI (#31479)
## Description This PR fixes following issues - JS and Query Blank state issue in side by side mode. - Added tooltip for minimize and maximize button. - Fixed add button getting squeezed issue. #### PR fixes following issue(s) Fixes https://github.com/appsmithorg/appsmith/issues/31330 #### Media https://github.com/appsmithorg/appsmith/assets/87797149/e0e30e47-1f3a-447d-93a5-144e48360cec #### Type of change - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [ ] Manual - [ ] JUnit - [ ] 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 - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced tooltips for maximize and minimize buttons in the editor interface, enhancing user interaction. - Added new empty state components for JavaScript actions and queries, improving the user experience for adding new elements. - Implemented split-screen empty states for both JavaScript actions and queries, catering to users who prefer side-by-side editing. - **Enhancements** - Updated the editor's segmented header and full-screen tabs with tooltips, providing clearer guidance on button functionalities. - Adjusted the maximum width of tabs in the editor to accommodate additional elements, ensuring a more organized display. - **Refactor** - Replaced the use of `EmptyState` with new `Empty` components in JavaScript and Query editor panes, streamlining the interface and aligning with new functionalities. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
7258ab51c5
commit
46b4252ae6
|
|
@ -2455,3 +2455,7 @@ export const HEADER_TITLES = {
|
|||
export const PASTE_FAILED = (str: string): string => `Paste failed! ${str}`;
|
||||
|
||||
export const CREATE_A_NEW_ITEM = (item: string) => `Create a new ${item}`;
|
||||
|
||||
export const MAXIMIZE_BUTTON_TOOLTIP = () =>
|
||||
`Expand code editor to full-screen`;
|
||||
export const MINIMIZE_BUTTON_TOOLTIP = () => `Open code editor next to the UI`;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import JSEditor from "pages/Editor/JSEditor";
|
|||
import AddJS from "pages/Editor/IDE/EditorPane/JS/Add";
|
||||
import { ADD_PATH } from "@appsmith/constants/routes/appRoutes";
|
||||
import ListJS from "pages/Editor/IDE/EditorPane/JS/List";
|
||||
import { BlankStateContainer } from "pages/Editor/IDE/EditorPane/JS/BlankStateContainer";
|
||||
|
||||
export const useJSAdd = () => {
|
||||
const pageId = useSelector(getCurrentPageId);
|
||||
|
|
@ -56,6 +57,12 @@ export const useJSSegmentRoutes = (path: string): UseRoutes => {
|
|||
component: JSEditor,
|
||||
path: [path + "/:collectionId"],
|
||||
},
|
||||
{
|
||||
key: "JSEmpty",
|
||||
component: BlankStateContainer,
|
||||
exact: true,
|
||||
path: [path],
|
||||
},
|
||||
];
|
||||
}
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import type { AppState } from "@appsmith/reducers";
|
|||
import keyBy from "lodash/keyBy";
|
||||
import { getPluginEntityIcon } from "pages/Editor/Explorer/ExplorerIcons";
|
||||
import type { ListItemProps } from "design-system";
|
||||
import { BlankStateContainer } from "pages/Editor/IDE/EditorPane/Query/BlankStateContainer";
|
||||
|
||||
export const useQueryAdd = () => {
|
||||
const location = useLocation();
|
||||
|
|
@ -96,6 +97,7 @@ export const useGroupedAddQueryOperations = (): GroupedAddOperations => {
|
|||
export const useQuerySegmentRoutes = (path: string): UseRoutes => {
|
||||
const isSideBySideEnabled = useSelector(getIsSideBySideEnabled);
|
||||
const editorMode = useSelector(getIDEViewMode);
|
||||
|
||||
if (isSideBySideEnabled && editorMode === EditorViewMode.SplitScreen) {
|
||||
return [
|
||||
{
|
||||
|
|
@ -130,6 +132,12 @@ export const useQuerySegmentRoutes = (path: string): UseRoutes => {
|
|||
exact: true,
|
||||
path: [path + "/:queryId"],
|
||||
},
|
||||
{
|
||||
key: "QueryEmpty",
|
||||
component: BlankStateContainer,
|
||||
exact: true,
|
||||
path: [path],
|
||||
},
|
||||
];
|
||||
}
|
||||
return [
|
||||
|
|
|
|||
32
app/client/src/pages/Editor/IDE/EditorPane/JS/BlankState.tsx
Normal file
32
app/client/src/pages/Editor/IDE/EditorPane/JS/BlankState.tsx
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import React from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
import { EDITOR_PANE_TEXTS, createMessage } from "@appsmith/constants/messages";
|
||||
import { getPagePermissions } from "selectors/editorSelectors";
|
||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
|
||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import { useJSAdd } from "@appsmith/pages/Editor/IDE/EditorPane/JS/hooks";
|
||||
import { EmptyState } from "../components/EmptyState";
|
||||
|
||||
const BlankState: React.FC = () => {
|
||||
const pagePermissions = useSelector(getPagePermissions);
|
||||
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
|
||||
const canCreateActions = getHasCreateActionPermission(
|
||||
isFeatureEnabled,
|
||||
pagePermissions,
|
||||
);
|
||||
const addButtonClickHandler = useJSAdd();
|
||||
|
||||
return (
|
||||
<EmptyState
|
||||
buttonClassName="t--add-item"
|
||||
buttonText={createMessage(EDITOR_PANE_TEXTS.js_add_button)}
|
||||
description={createMessage(EDITOR_PANE_TEXTS.js_blank_state_description)}
|
||||
icon={"js-square-v3"}
|
||||
onClick={canCreateActions ? addButtonClickHandler : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { BlankState };
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import React from "react";
|
||||
import { Flex } from "design-system";
|
||||
|
||||
import { BlankState } from "./BlankState";
|
||||
|
||||
const BlankStateContainer: React.FC = () => {
|
||||
return (
|
||||
<Flex flexDirection="column" gap="spaces-3" overflow="hidden" py="spaces-3">
|
||||
<BlankState />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export { BlankStateContainer };
|
||||
|
|
@ -14,11 +14,11 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
|||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
|
||||
import { createMessage, EDITOR_PANE_TEXTS } from "@appsmith/constants/messages";
|
||||
import { EmptyState } from "../components/EmptyState";
|
||||
import { ActionParentEntityType } from "@appsmith/entities/Engine/actionHelpers";
|
||||
import { FilesContextProvider } from "pages/Editor/Explorer/Files/FilesContextProvider";
|
||||
import { useJSAdd } from "@appsmith/pages/Editor/IDE/EditorPane/JS/hooks";
|
||||
import { JSListItem } from "@appsmith/pages/Editor/IDE/EditorPane/JS/ListItem";
|
||||
import { BlankState } from "./BlankState";
|
||||
|
||||
const JSContainer = styled(Flex)`
|
||||
& .t--entity-item {
|
||||
|
|
@ -114,17 +114,7 @@ const ListJSObjects = () => {
|
|||
</Flex>
|
||||
</FilesContextProvider>
|
||||
|
||||
{(!jsList || jsList.length === 0) && (
|
||||
<EmptyState
|
||||
buttonClassName="t--add-item"
|
||||
buttonText={createMessage(EDITOR_PANE_TEXTS.js_add_button)}
|
||||
description={createMessage(
|
||||
EDITOR_PANE_TEXTS.js_blank_state_description,
|
||||
)}
|
||||
icon={"js-square-v3"}
|
||||
onClick={canCreateActions ? addButtonClickHandler : undefined}
|
||||
/>
|
||||
)}
|
||||
{(!jsList || jsList.length === 0) && <BlankState />}
|
||||
</JSContainer>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
import React from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
import { EDITOR_PANE_TEXTS, createMessage } from "@appsmith/constants/messages";
|
||||
import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers";
|
||||
import { getPagePermissions } from "selectors/editorSelectors";
|
||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import { EmptyState } from "../components/EmptyState";
|
||||
import { useQueryAdd } from "@appsmith/pages/Editor/IDE/EditorPane/Query/hooks";
|
||||
|
||||
const BlankState: React.FC = () => {
|
||||
const pagePermissions = useSelector(getPagePermissions);
|
||||
const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);
|
||||
const canCreateActions = getHasCreateActionPermission(
|
||||
isFeatureEnabled,
|
||||
pagePermissions,
|
||||
);
|
||||
const addButtonClickHandler = useQueryAdd();
|
||||
|
||||
return (
|
||||
<EmptyState
|
||||
buttonClassName="t--add-item"
|
||||
buttonText={createMessage(EDITOR_PANE_TEXTS.query_add_button)}
|
||||
description={createMessage(
|
||||
EDITOR_PANE_TEXTS.query_blank_state_description,
|
||||
)}
|
||||
icon={"queries-v3"}
|
||||
onClick={canCreateActions ? addButtonClickHandler : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { BlankState };
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import React from "react";
|
||||
import { Flex } from "design-system";
|
||||
|
||||
import { BlankState } from "./BlankState";
|
||||
|
||||
const BlankStateContainer: React.FC = () => {
|
||||
return (
|
||||
<Flex
|
||||
flex="1"
|
||||
flexDirection="column"
|
||||
gap="spaces-3"
|
||||
overflow="hidden"
|
||||
py="spaces-3"
|
||||
>
|
||||
<BlankState />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export { BlankStateContainer };
|
||||
|
|
@ -15,10 +15,10 @@ import { selectQuerySegmentEditorList } from "@appsmith/selectors/appIDESelector
|
|||
import { ActionParentEntityType } from "@appsmith/entities/Engine/actionHelpers";
|
||||
import { FilesContextProvider } from "pages/Editor/Explorer/Files/FilesContextProvider";
|
||||
import { createMessage, EDITOR_PANE_TEXTS } from "@appsmith/constants/messages";
|
||||
import { EmptyState } from "../components/EmptyState";
|
||||
import { useQueryAdd } from "@appsmith/pages/Editor/IDE/EditorPane/Query/hooks";
|
||||
import { QueryListItem } from "@appsmith/pages/Editor/IDE/EditorPane/Query/ListItem";
|
||||
import { getShowWorkflowFeature } from "@appsmith/selectors/workflowSelectors";
|
||||
import { BlankState } from "./BlankState";
|
||||
|
||||
const ListQuery = () => {
|
||||
const pageId = useSelector(getCurrentPageId) as string;
|
||||
|
|
@ -98,17 +98,7 @@ const ListQuery = () => {
|
|||
})}
|
||||
</Flex>
|
||||
|
||||
{Object.keys(files).length === 0 && (
|
||||
<EmptyState
|
||||
buttonClassName="t--add-item"
|
||||
buttonText={createMessage(EDITOR_PANE_TEXTS.query_add_button)}
|
||||
description={createMessage(
|
||||
EDITOR_PANE_TEXTS.query_blank_state_description,
|
||||
)}
|
||||
icon={"queries-v3"}
|
||||
onClick={canCreateActions ? addButtonClickHandler : undefined}
|
||||
/>
|
||||
)}
|
||||
{Object.keys(files).length === 0 && <BlankState />}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import React from "react";
|
||||
import { Button, Flex, SegmentedControl } from "design-system";
|
||||
import { createMessage, EDITOR_PANE_TEXTS } from "@appsmith/constants/messages";
|
||||
import { Button, Flex, SegmentedControl, Tooltip } from "design-system";
|
||||
import {
|
||||
createMessage,
|
||||
EDITOR_PANE_TEXTS,
|
||||
MAXIMIZE_BUTTON_TOOLTIP,
|
||||
} from "@appsmith/constants/messages";
|
||||
import {
|
||||
EditorEntityTab,
|
||||
EditorViewMode,
|
||||
|
|
@ -82,15 +86,17 @@ const SegmentedHeader = () => {
|
|||
{isSideBySideEnabled &&
|
||||
editorMode === EditorViewMode.SplitScreen &&
|
||||
segment !== EditorEntityTab.UI ? (
|
||||
<Button
|
||||
id="editor-mode-maximize"
|
||||
isIconButton
|
||||
kind="tertiary"
|
||||
onClick={() =>
|
||||
dispatch(setIdeEditorViewMode(EditorViewMode.FullScreen))
|
||||
}
|
||||
startIcon="maximize-v3"
|
||||
/>
|
||||
<Tooltip content={createMessage(MAXIMIZE_BUTTON_TOOLTIP)}>
|
||||
<Button
|
||||
id="editor-mode-maximize"
|
||||
isIconButton
|
||||
kind="tertiary"
|
||||
onClick={() =>
|
||||
dispatch(setIdeEditorViewMode(EditorViewMode.FullScreen))
|
||||
}
|
||||
startIcon="maximize-v3"
|
||||
/>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</Container>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useCallback } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Button } from "design-system";
|
||||
import { Button, Tooltip } from "design-system";
|
||||
import { getIDEViewMode, getIsSideBySideEnabled } from "selectors/ideSelectors";
|
||||
import type { EntityItem } from "@appsmith/entities/IDE/constants";
|
||||
import {
|
||||
|
|
@ -14,6 +14,10 @@ import { useCurrentEditorState } from "../hooks";
|
|||
import { getCurrentPageId } from "@appsmith/selectors/entitiesSelector";
|
||||
import history, { NavigationMethod } from "utils/history";
|
||||
import { TabSelectors } from "./constants";
|
||||
import {
|
||||
MINIMIZE_BUTTON_TOOLTIP,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
|
||||
const FullScreenTabs = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
|
@ -44,13 +48,18 @@ const FullScreenTabs = () => {
|
|||
return (
|
||||
<Container>
|
||||
<FileTabs navigateToTab={onClick} tabs={files} />
|
||||
<Button
|
||||
id="editor-mode-minimize"
|
||||
isIconButton
|
||||
kind="tertiary"
|
||||
onClick={setSplitScreenMode}
|
||||
startIcon="minimize-v3"
|
||||
/>
|
||||
<Tooltip
|
||||
content={createMessage(MINIMIZE_BUTTON_TOOLTIP)}
|
||||
placement="bottomRight"
|
||||
>
|
||||
<Button
|
||||
id="editor-mode-minimize"
|
||||
isIconButton
|
||||
kind="tertiary"
|
||||
onClick={setSplitScreenMode}
|
||||
startIcon="minimize-v3"
|
||||
/>
|
||||
</Tooltip>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ const SplitScreenTabs = () => {
|
|||
if (!isSideBySideEnabled) return null;
|
||||
if (ideViewMode === EditorViewMode.FullScreen) return null;
|
||||
if (segment === EditorEntityTab.UI) return null;
|
||||
return (
|
||||
return files.length > 0 ? (
|
||||
<Container>
|
||||
<Button
|
||||
isIconButton
|
||||
|
|
@ -65,7 +65,7 @@ const SplitScreenTabs = () => {
|
|||
<FileTabs navigateToTab={onClick} tabs={files} />
|
||||
<ListButton items={overflowList} navigateToTab={onClick} />
|
||||
</Container>
|
||||
);
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default SplitScreenTabs;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ import { DEFAULT_SPLIT_SCREEN_WIDTH } from "constants/AppConstants";
|
|||
* 4px gap between every tabs * 4 (since max tab count is 5,
|
||||
* there will be 5 gaps)
|
||||
* 26px Add button width
|
||||
* 62px show more list button(considering 3 digit width as max)
|
||||
* ======================================
|
||||
* 54px
|
||||
* 116px
|
||||
*
|
||||
*/
|
||||
export const StyledTab = styled(Flex)`
|
||||
|
|
@ -28,7 +29,7 @@ export const StyledTab = styled(Flex)`
|
|||
border-top-right-radius: var(--ads-v2-border-radius);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
max-width: calc((${DEFAULT_SPLIT_SCREEN_WIDTH} - 54px) / 5);
|
||||
max-width: calc((${DEFAULT_SPLIT_SCREEN_WIDTH} - 116px) / 5);
|
||||
|
||||
// After element - the seperator in between tabs
|
||||
&:not(&.active):not(:has(+ .active)):not(:last-child):after {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user