chore: Transitions for IDE (#35714)
## Description Uses `AnimatedGridLayout` component to introduce transitions for the IDE. This is behind a feature flag Fixes #34538 Fixes #30863 Fixes #34544 ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!CAUTION] > 🔴 🔴 🔴 Some tests have failed. > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/10737363879> > Commit: a912f5c52366abe48768727a1c605cd72b48752c > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10737363879&attempt=2&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank">Cypress dashboard</a>. > Tags: @tag.All > Spec: > The following are new failures, please fix them before merging the PR: <ol> > <li>cypress/e2e/Regression/ServerSide/OnLoadTests/ExecuteAction_Spec.ts</ol> > <a href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master" target="_blank">List of identified flaky tests</a>. > <hr>Fri, 06 Sep 2024 16:32:30 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **New Features** - Introduced two new layout components: `AnimatedLayout` and `UnanimatedLayout` for improved editor interface structuring. - Added TypeScript type definitions for the DOM View Transitions API to enhance type safety and developer experience. - Implemented custom hooks, `useGridLayoutTemplate` and `useEditorStateLeftPaneWidth`, for dynamic grid management and left pane width calculation in the IDE layout. - **Improvements** - Enhanced layout responsiveness with the addition of dynamic grid management. - Updated the `Editor` component to use a centralized constant for height calculations, improving maintainability and consistency. - Enhanced test accuracy by refining assertions in the Git Branch Protection test suite. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Sagar Khalasi <sagar@appsmith.com>
This commit is contained in:
parent
1b16be896d
commit
60dbda49e7
|
|
@ -36,10 +36,7 @@ describe("Git Branch Protection", { tags: ["@tag.Git"] }, function () {
|
||||||
cy.wait("@gitProtectApi").then((res1) => {
|
cy.wait("@gitProtectApi").then((res1) => {
|
||||||
_.agHelper.GetNClick(_.gitSync._closeGitSettingsModal);
|
_.agHelper.GetNClick(_.gitSync._closeGitSettingsModal);
|
||||||
expect(res1.response).to.have.property("statusCode", 200);
|
expect(res1.response).to.have.property("statusCode", 200);
|
||||||
_.agHelper.AssertElementVisibility(
|
_.agHelper.AssertElementAbsence(AppSidebar.locators.sidebar);
|
||||||
AppSidebar.locators.sidebar,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
_.agHelper.AssertElementVisibility(
|
_.agHelper.AssertElementVisibility(
|
||||||
PageLeftPane.locators.selector,
|
PageLeftPane.locators.selector,
|
||||||
false,
|
false,
|
||||||
|
|
|
||||||
|
|
@ -269,6 +269,7 @@
|
||||||
"@types/codemirror": "^0.0.96",
|
"@types/codemirror": "^0.0.96",
|
||||||
"@types/deep-diff": "^1.0.0",
|
"@types/deep-diff": "^1.0.0",
|
||||||
"@types/dom-mediacapture-record": "^1.0.11",
|
"@types/dom-mediacapture-record": "^1.0.11",
|
||||||
|
"@types/dom-view-transitions": "^1.0.5",
|
||||||
"@types/downloadjs": "^1.4.2",
|
"@types/downloadjs": "^1.4.2",
|
||||||
"@types/jest": "^27.4.1",
|
"@types/jest": "^27.4.1",
|
||||||
"@types/js-beautify": "^1.13.2",
|
"@types/js-beautify": "^1.13.2",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Divider, Flex } from "@appsmith/ads";
|
import { Divider, Flex } from "@appsmith/ads";
|
||||||
import { AppsmithLink } from "pages/Editor/AppsmithLink";
|
import { AppsmithLink } from "pages/Editor/AppsmithLink";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "./constants";
|
||||||
|
|
||||||
interface ChildrenProps {
|
interface ChildrenProps {
|
||||||
children: React.ReactNode | React.ReactNode[];
|
children: React.ReactNode | React.ReactNode[];
|
||||||
|
|
@ -59,7 +60,7 @@ const Header = (props: ChildrenProps) => {
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
border="1px solid var(--ads-v2-color-border)"
|
border="1px solid var(--ads-v2-color-border)"
|
||||||
className="t--editor-header"
|
className="t--editor-header"
|
||||||
height="40px"
|
height={IDE_HEADER_HEIGHT + "px"}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
width="100%"
|
width="100%"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
1
app/client/src/IDE/Structure/constants.ts
Normal file
1
app/client/src/IDE/Structure/constants.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const IDE_HEADER_HEIGHT = 40;
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
* These are composable components that you can use to spread the content of the header
|
* These are composable components that you can use to spread the content of the header
|
||||||
* It is possible to use the IDE Header without using these subsections
|
* It is possible to use the IDE Header without using these subsections
|
||||||
*/
|
*/
|
||||||
|
export { IDE_HEADER_HEIGHT } from "./Structure/constants";
|
||||||
export { default as IDEHeader } from "./Structure/Header";
|
export { default as IDEHeader } from "./Structure/Header";
|
||||||
|
|
||||||
/* ====================================================
|
/* ====================================================
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ export const FEATURE_FLAG = {
|
||||||
"ab_learnability_discoverability_collapse_all_except_data_enabled",
|
"ab_learnability_discoverability_collapse_all_except_data_enabled",
|
||||||
release_layout_conversion_enabled: "release_layout_conversion_enabled",
|
release_layout_conversion_enabled: "release_layout_conversion_enabled",
|
||||||
release_anvil_toggle_enabled: "release_anvil_toggle_enabled",
|
release_anvil_toggle_enabled: "release_anvil_toggle_enabled",
|
||||||
|
release_ide_animations_enabled: "release_ide_animations_enabled",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type FeatureFlag = keyof typeof FEATURE_FLAG;
|
export type FeatureFlag = keyof typeof FEATURE_FLAG;
|
||||||
|
|
@ -82,6 +83,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
|
||||||
ab_learnability_discoverability_collapse_all_except_data_enabled: true,
|
ab_learnability_discoverability_collapse_all_except_data_enabled: true,
|
||||||
release_layout_conversion_enabled: false,
|
release_layout_conversion_enabled: false,
|
||||||
release_anvil_toggle_enabled: false,
|
release_anvil_toggle_enabled: false,
|
||||||
|
release_ide_animations_enabled: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AB_TESTING_EVENT_KEYS = {
|
export const AB_TESTING_EVENT_KEYS = {
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ export function LayoutArea(props: LayoutAreaProps) {
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
minWidth: dimensions?.width || "100%",
|
width: dimensions?.width || "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
import { easings } from "@react-spring/web";
|
|
||||||
import type { AnimatedGridUnit } from "./types";
|
import type { AnimatedGridUnit } from "./types";
|
||||||
|
|
||||||
/** Default rows config. */
|
/** Default rows config. */
|
||||||
export const DEFAULT_ROWS: AnimatedGridUnit[] = ["1fr"];
|
export const DEFAULT_ROWS: AnimatedGridUnit[] = ["1fr"];
|
||||||
|
|
||||||
export const SPRING_ANIMATION_CONFIG = {
|
export const SPRING_ANIMATION_CONFIG = {
|
||||||
easing: easings.easeInCirc,
|
duration: 375,
|
||||||
|
friction: 32,
|
||||||
|
mass: 1,
|
||||||
|
tension: 205,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Layers } from "constants/Layers";
|
import { Layers } from "constants/Layers";
|
||||||
|
import { BOTTOM_BAR_HEIGHT } from "./constants";
|
||||||
|
|
||||||
export const Container = styled.div`
|
export const Container = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: ${(props) => props.theme.bottomBarHeight};
|
height: ${BOTTOM_BAR_HEIGHT}px;
|
||||||
display: flex;
|
display: flex;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
|
||||||
1
app/client/src/components/BottomBar/constants.ts
Normal file
1
app/client/src/components/BottomBar/constants.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const BOTTOM_BAR_HEIGHT = 37;
|
||||||
|
|
@ -7,14 +7,18 @@ import { Button } from "@appsmith/ads";
|
||||||
import SwitchEnvironment from "ee/components/SwitchEnvironment";
|
import SwitchEnvironment from "ee/components/SwitchEnvironment";
|
||||||
import { Container, Wrapper } from "./components";
|
import { Container, Wrapper } from "./components";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { getCurrentApplicationId } from "selectors/editorSelectors";
|
import {
|
||||||
|
getCurrentApplicationId,
|
||||||
|
previewModeSelector,
|
||||||
|
} from "selectors/editorSelectors";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { softRefreshActions } from "actions/pluginActionActions";
|
import { softRefreshActions } from "actions/pluginActionActions";
|
||||||
import { START_SWITCH_ENVIRONMENT } from "ee/constants/messages";
|
import { START_SWITCH_ENVIRONMENT } from "ee/constants/messages";
|
||||||
import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors";
|
import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors";
|
||||||
|
|
||||||
export default function BottomBar({ viewMode }: { viewMode: boolean }) {
|
export default function BottomBar() {
|
||||||
const appId = useSelector(getCurrentApplicationId) || "";
|
const appId = useSelector(getCurrentApplicationId) || "";
|
||||||
|
const isPreviewMode = useSelector(previewModeSelector);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
// We check if the current application is an Anvil application.
|
// We check if the current application is an Anvil application.
|
||||||
// If it is an Anvil application, we remove the Git features from the bottomBar
|
// If it is an Anvil application, we remove the Git features from the bottomBar
|
||||||
|
|
@ -28,17 +32,17 @@ export default function BottomBar({ viewMode }: { viewMode: boolean }) {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
{!viewMode && (
|
{!isPreviewMode && (
|
||||||
<SwitchEnvironment
|
<SwitchEnvironment
|
||||||
editorId={appId}
|
editorId={appId}
|
||||||
onChangeEnv={onChangeEnv}
|
onChangeEnv={onChangeEnv}
|
||||||
startSwitchEnvMessage={START_SWITCH_ENVIRONMENT}
|
startSwitchEnvMessage={START_SWITCH_ENVIRONMENT}
|
||||||
viewMode={viewMode}
|
viewMode={isPreviewMode}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!viewMode && !isAnvilEnabled && <QuickGitActions />}
|
{!isPreviewMode && !isAnvilEnabled && <QuickGitActions />}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
{!viewMode && (
|
{!isPreviewMode && (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<ManualUpgrades showTooltip>
|
<ManualUpgrades showTooltip>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -1,51 +1,28 @@
|
||||||
import classNames from "classnames";
|
import React, {
|
||||||
|
memo,
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
} from "react";
|
||||||
import * as Sentry from "@sentry/react";
|
import * as Sentry from "@sentry/react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import React, { memo, useContext, useEffect, useMemo, useRef } from "react";
|
|
||||||
|
|
||||||
import { getSelectedWidgets } from "selectors/ui";
|
import { getSelectedWidgets } from "selectors/ui";
|
||||||
import { tailwindLayers } from "constants/Layers";
|
|
||||||
import WidgetPropertyPane from "pages/Editor/PropertyPane";
|
import WidgetPropertyPane from "pages/Editor/PropertyPane";
|
||||||
import CanvasPropertyPane from "pages/Editor/CanvasPropertyPane";
|
import CanvasPropertyPane from "pages/Editor/CanvasPropertyPane";
|
||||||
import useHorizontalResize from "utils/hooks/useHorizontalResize";
|
|
||||||
import { getIsDraggingForSelection } from "selectors/canvasSelectors";
|
|
||||||
import MultiSelectPropertyPane from "pages/Editor/MultiSelectPropertyPane";
|
import MultiSelectPropertyPane from "pages/Editor/MultiSelectPropertyPane";
|
||||||
import { getIsDraggingOrResizing } from "selectors/widgetSelectors";
|
import { getIsDraggingOrResizing } from "selectors/widgetSelectors";
|
||||||
import { selectedWidgetsPresentInCanvas } from "selectors/propertyPaneSelectors";
|
import { selectedWidgetsPresentInCanvas } from "selectors/propertyPaneSelectors";
|
||||||
import styled from "styled-components";
|
|
||||||
import WalkthroughContext from "components/featureWalkthrough/walkthroughContext";
|
import WalkthroughContext from "components/featureWalkthrough/walkthroughContext";
|
||||||
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
||||||
|
|
||||||
export const PROPERTY_PANE_ID = "t--property-pane-sidebar";
|
export const PROPERTY_PANE_ID = "t--property-pane-sidebar";
|
||||||
|
|
||||||
const StyledResizer = styled.div<{ resizing: boolean }>`
|
export const PropertyPaneSidebar = memo(() => {
|
||||||
${(props) =>
|
|
||||||
props.resizing &&
|
|
||||||
`
|
|
||||||
& > div {
|
|
||||||
background-color: var(--ads-v2-color-outline);
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
:hover {
|
|
||||||
& > div {
|
|
||||||
background-color: var(--ads-v2-color-bg-emphasis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
width: number;
|
|
||||||
onDragEnd?: () => void;
|
|
||||||
onWidthChange: (width: number) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PropertyPaneSidebar = memo((props: Props) => {
|
|
||||||
const sidebarRef = useRef<HTMLDivElement>(null);
|
const sidebarRef = useRef<HTMLDivElement>(null);
|
||||||
const prevSelectedWidgetId = useRef<string | undefined>();
|
const prevSelectedWidgetId = useRef<string | undefined>();
|
||||||
|
|
||||||
const { onMouseDown, onMouseUp, onTouchStart, resizing } =
|
|
||||||
useHorizontalResize(sidebarRef, props.onWidthChange, props.onDragEnd, true);
|
|
||||||
|
|
||||||
const selectedWidgetIds = useSelector(getSelectedWidgets);
|
const selectedWidgetIds = useSelector(getSelectedWidgets);
|
||||||
const isDraggingOrResizing = useSelector(getIsDraggingOrResizing);
|
const isDraggingOrResizing = useSelector(getIsDraggingOrResizing);
|
||||||
const { isOpened: isWalkthroughOpened, popFeature } =
|
const { isOpened: isWalkthroughOpened, popFeature } =
|
||||||
|
|
@ -58,17 +35,10 @@ export const PropertyPaneSidebar = memo((props: Props) => {
|
||||||
selectedWidgetIds[0] !== prevSelectedWidgetId.current) ||
|
selectedWidgetIds[0] !== prevSelectedWidgetId.current) ||
|
||||||
selectedWidgetIds[0] === MAIN_CONTAINER_WIDGET_ID;
|
selectedWidgetIds[0] === MAIN_CONTAINER_WIDGET_ID;
|
||||||
|
|
||||||
// This is to keep the theming properties from changing,
|
|
||||||
// while dragging a widget when no other widgets were selected
|
|
||||||
const keepThemeWhileDragging =
|
|
||||||
prevSelectedWidgetId.current === undefined && shouldNotRenderPane;
|
|
||||||
|
|
||||||
const selectedWidgetsLength = useSelector(
|
const selectedWidgetsLength = useSelector(
|
||||||
(state) => selectedWidgetsPresentInCanvas(state).length,
|
(state) => selectedWidgetsPresentInCanvas(state).length,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isDraggingForSelection = useSelector(getIsDraggingForSelection);
|
|
||||||
|
|
||||||
prevSelectedWidgetId.current =
|
prevSelectedWidgetId.current =
|
||||||
selectedWidgetIds.length === 1 ? selectedWidgetIds[0] : undefined;
|
selectedWidgetIds.length === 1 ? selectedWidgetIds[0] : undefined;
|
||||||
|
|
||||||
|
|
@ -91,27 +61,24 @@ export const PropertyPaneSidebar = memo((props: Props) => {
|
||||||
default:
|
default:
|
||||||
return <CanvasPropertyPane />;
|
return <CanvasPropertyPane />;
|
||||||
}
|
}
|
||||||
}, [
|
}, [selectedWidgetsLength, shouldNotRenderPane]);
|
||||||
selectedWidgetsLength,
|
|
||||||
isDraggingForSelection,
|
|
||||||
shouldNotRenderPane,
|
|
||||||
keepThemeWhileDragging,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const closeWalkthrough = () => {
|
const closeWalkthrough = useCallback(() => {
|
||||||
if (popFeature) {
|
if (popFeature) {
|
||||||
popFeature("PROPERTY_PANE");
|
popFeature("PROPERTY_PANE");
|
||||||
sidebarRef.current?.removeEventListener("click", closeWalkthrough);
|
sidebarRef.current?.removeEventListener("click", closeWalkthrough);
|
||||||
}
|
}
|
||||||
};
|
}, [popFeature]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isWalkthroughOpened)
|
const currentSidebar = sidebarRef.current;
|
||||||
sidebarRef.current?.addEventListener("click", closeWalkthrough);
|
if (isWalkthroughOpened) {
|
||||||
|
currentSidebar?.addEventListener("click", closeWalkthrough);
|
||||||
|
}
|
||||||
return () => {
|
return () => {
|
||||||
sidebarRef.current?.removeEventListener("click", closeWalkthrough);
|
currentSidebar?.removeEventListener("click", closeWalkthrough);
|
||||||
};
|
};
|
||||||
}, [isWalkthroughOpened]);
|
}, [closeWalkthrough, isWalkthroughOpened]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative h-full">
|
<div className="relative h-full">
|
||||||
|
|
@ -122,28 +89,7 @@ export const PropertyPaneSidebar = memo((props: Props) => {
|
||||||
id={PROPERTY_PANE_ID}
|
id={PROPERTY_PANE_ID}
|
||||||
ref={sidebarRef}
|
ref={sidebarRef}
|
||||||
>
|
>
|
||||||
{/* RESIZER */}
|
<div className={"h-full p-0 overflow-y-auto min-w-72 max-w-104 w-full"}>
|
||||||
<StyledResizer
|
|
||||||
className={`absolute top-0 left-0 w-2 h-full -ml-1 group cursor-ew-resize ${tailwindLayers.resizer}`}
|
|
||||||
onMouseDown={onMouseDown}
|
|
||||||
onTouchEnd={onMouseUp}
|
|
||||||
onTouchStart={onTouchStart}
|
|
||||||
resizing={resizing}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={classNames({
|
|
||||||
"w-1 h-full bg-transparent transform transition flex items-center":
|
|
||||||
true,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</StyledResizer>
|
|
||||||
<div
|
|
||||||
className={classNames({
|
|
||||||
"h-full p-0 overflow-y-auto min-w-72 max-w-104": true,
|
|
||||||
"transition-all duration-400": !resizing,
|
|
||||||
})}
|
|
||||||
style={{ width: props.width }}
|
|
||||||
>
|
|
||||||
{propertyPane}
|
{propertyPane}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ import React, { useEffect, useState } from "react";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Layers } from "constants/Layers";
|
import { Layers } from "constants/Layers";
|
||||||
import { theme } from "constants/DefaultTheme";
|
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { getAppViewHeaderHeight } from "selectors/appViewSelectors";
|
import { getAppViewHeaderHeight } from "selectors/appViewSelectors";
|
||||||
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
||||||
import { useMaxModalWidth } from "widgets/ModalWidget/component/useModalWidth";
|
import { useMaxModalWidth } from "widgets/ModalWidget/component/useModalWidth";
|
||||||
import { useAppViewerSidebarProperties } from "utils/hooks/useAppViewerSidebarProperties";
|
import { useAppViewerSidebarProperties } from "utils/hooks/useAppViewerSidebarProperties";
|
||||||
|
|
||||||
const Container = styled.div<{
|
const Container = styled.div<{
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
|
@ -22,7 +22,6 @@ const Container = styled.div<{
|
||||||
minSize?: number;
|
minSize?: number;
|
||||||
isEditMode?: boolean;
|
isEditMode?: boolean;
|
||||||
headerHeight?: number;
|
headerHeight?: number;
|
||||||
smallHeaderHeight?: string;
|
|
||||||
leftSidebarWidth?: string;
|
leftSidebarWidth?: string;
|
||||||
}>`
|
}>`
|
||||||
&&& {
|
&&& {
|
||||||
|
|
@ -152,7 +151,6 @@ export function ModalOverlayLayer(props: BaseWidgetProps) {
|
||||||
maxWidth={maxModalWidth}
|
maxWidth={maxModalWidth}
|
||||||
minSize={props.minSize}
|
minSize={props.minSize}
|
||||||
right={props.bottom}
|
right={props.bottom}
|
||||||
smallHeaderHeight={theme.smallHeaderHeight}
|
|
||||||
top={props.top}
|
top={props.top}
|
||||||
width={props.width}
|
width={props.width}
|
||||||
zIndex={
|
zIndex={
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Classes } from "@blueprintjs/core";
|
import { Classes } from "@blueprintjs/core";
|
||||||
import { Link, Text } from "@appsmith/ads";
|
import { Link, Text } from "@appsmith/ads";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "IDE";
|
||||||
|
|
||||||
export const Wrapper = styled.div`
|
export const Wrapper = styled.div`
|
||||||
flex-basis: calc(100% - ${(props) => props.theme.homePage.leftPane.width}px);
|
flex-basis: calc(100% - ${(props) => props.theme.homePage.leftPane.width}px);
|
||||||
|
|
@ -37,7 +38,7 @@ export const BottomSpace = styled.div`
|
||||||
export const ContentWrapper = styled.div``;
|
export const ContentWrapper = styled.div``;
|
||||||
|
|
||||||
export const LoaderContainer = styled.div`
|
export const LoaderContainer = styled.div`
|
||||||
height: ${(props) => `calc(100vh - ${props.theme.smallHeaderHeight})`};
|
height: calc(100vh - ${IDE_HEADER_HEIGHT}px);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,12 @@ import {
|
||||||
StyledMenuContainer,
|
StyledMenuContainer,
|
||||||
StyledSidebar,
|
StyledSidebar,
|
||||||
} from "./Sidebar.styled";
|
} from "./Sidebar.styled";
|
||||||
import { getCurrentThemeDetails } from "selectors/themeSelectors";
|
|
||||||
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
|
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
|
||||||
import NavigationLogo from "ee/pages/AppViewer/NavigationLogo";
|
import NavigationLogo from "ee/pages/AppViewer/NavigationLogo";
|
||||||
import MenuItemContainer from "./components/MenuItemContainer";
|
import MenuItemContainer from "./components/MenuItemContainer";
|
||||||
import BackToAppsButton from "./components/BackToAppsButton";
|
import BackToAppsButton from "./components/BackToAppsButton";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "IDE";
|
||||||
|
import { BOTTOM_BAR_HEIGHT } from "components/BottomBar/constants";
|
||||||
|
|
||||||
interface SidebarProps {
|
interface SidebarProps {
|
||||||
currentApplicationDetails?: ApplicationPayload;
|
currentApplicationDetails?: ApplicationPayload;
|
||||||
|
|
@ -80,7 +81,6 @@ export function Sidebar(props: SidebarProps) {
|
||||||
const isPinned = useSelector(getAppSidebarPinned);
|
const isPinned = useSelector(getAppSidebarPinned);
|
||||||
const [isOpen, setIsOpen] = useState(true);
|
const [isOpen, setIsOpen] = useState(true);
|
||||||
const { x } = useMouse();
|
const { x } = useMouse();
|
||||||
const theme = useSelector(getCurrentThemeDetails);
|
|
||||||
const isPreviewMode = useSelector(combinedPreviewModeSelector);
|
const isPreviewMode = useSelector(combinedPreviewModeSelector);
|
||||||
const isAppSettingsPaneWithNavigationTabOpen = useSelector(
|
const isAppSettingsPaneWithNavigationTabOpen = useSelector(
|
||||||
getIsAppSettingsPaneWithNavigationTabOpen,
|
getIsAppSettingsPaneWithNavigationTabOpen,
|
||||||
|
|
@ -127,10 +127,10 @@ export function Sidebar(props: SidebarProps) {
|
||||||
const suffix = ")";
|
const suffix = ")";
|
||||||
|
|
||||||
if (isPreviewMode) {
|
if (isPreviewMode) {
|
||||||
prefix += `${theme.smallHeaderHeight} - ${theme.bottomBarHeight}`;
|
prefix += `${IDE_HEADER_HEIGHT}px - ${BOTTOM_BAR_HEIGHT}px`;
|
||||||
} else if (isAppSettingsPaneWithNavigationTabOpen) {
|
} else if (isAppSettingsPaneWithNavigationTabOpen) {
|
||||||
// We deduct 64px as well since it is the margin coming from "m-8" class from tailwind
|
// We deduct 64px as well since it is the margin coming from "m-8" class from tailwind
|
||||||
prefix += `${theme.smallHeaderHeight} - ${theme.bottomBarHeight} - 64px`;
|
prefix += `${IDE_HEADER_HEIGHT}px - ${BOTTOM_BAR_HEIGHT}px - 64px`;
|
||||||
} else {
|
} else {
|
||||||
prefix += "0px";
|
prefix += "0px";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ const Canvas = (props: CanvasProps) => {
|
||||||
<Wrapper
|
<Wrapper
|
||||||
$enableMainCanvasResizer={!!props.enableMainCanvasResizer}
|
$enableMainCanvasResizer={!!props.enableMainCanvasResizer}
|
||||||
background={isAnvilLayout ? "" : backgroundForCanvas}
|
background={isAnvilLayout ? "" : backgroundForCanvas}
|
||||||
className={`relative t--canvas-artboard ${paddingBottomClass} transition-all duration-400 ${marginHorizontalClass} ${getViewportClassName(
|
className={`relative t--canvas-artboard ${paddingBottomClass} ${marginHorizontalClass} ${getViewportClassName(
|
||||||
canvasWidth,
|
canvasWidth,
|
||||||
)}`}
|
)}`}
|
||||||
data-testid={"t--canvas-artboard"}
|
data-testid={"t--canvas-artboard"}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import styled from "styled-components";
|
||||||
import { Classes } from "@blueprintjs/core";
|
import { Classes } from "@blueprintjs/core";
|
||||||
import { getTypographyByKey } from "@appsmith/ads-old";
|
import { getTypographyByKey } from "@appsmith/ads-old";
|
||||||
import { Icon } from "@appsmith/ads";
|
import { Icon } from "@appsmith/ads";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "IDE";
|
||||||
|
|
||||||
export const Container = styled.div`
|
export const Container = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -10,7 +11,7 @@ export const Container = styled.div`
|
||||||
background-color: var(--ads-v2-color-bg-subtle);
|
background-color: var(--ads-v2-color-bg-subtle);
|
||||||
}
|
}
|
||||||
& .${Classes.EDITABLE_TEXT} {
|
& .${Classes.EDITABLE_TEXT} {
|
||||||
height: ${(props) => props.theme.smallHeaderHeight} !important;
|
height: ${IDE_HEADER_HEIGHT} !important;
|
||||||
display: block;
|
display: block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
@ -21,9 +22,9 @@ export const Container = styled.div`
|
||||||
&&&& .${Classes.EDITABLE_TEXT_CONTENT}, &&&& .${Classes.EDITABLE_TEXT_INPUT} {
|
&&&& .${Classes.EDITABLE_TEXT_CONTENT}, &&&& .${Classes.EDITABLE_TEXT_INPUT} {
|
||||||
display: block;
|
display: block;
|
||||||
${getTypographyByKey("h5")};
|
${getTypographyByKey("h5")};
|
||||||
line-height: ${(props) => props.theme.smallHeaderHeight} !important;
|
line-height: ${IDE_HEADER_HEIGHT} !important;
|
||||||
padding: 0 ${(props) => props.theme.spaces[2]}px;
|
padding: 0 ${(props) => props.theme.spaces[2]}px;
|
||||||
height: ${(props) => props.theme.smallHeaderHeight} !important;
|
height: ${IDE_HEADER_HEIGHT} !important;
|
||||||
}
|
}
|
||||||
&&&& .${Classes.EDITABLE_TEXT_INPUT} {
|
&&&& .${Classes.EDITABLE_TEXT_INPUT} {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ import { ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
|
||||||
import {
|
import {
|
||||||
APP_SIDEBAR_WIDTH,
|
APP_SIDEBAR_WIDTH,
|
||||||
DEFAULT_EXPLORER_PANE_WIDTH,
|
DEFAULT_EXPLORER_PANE_WIDTH,
|
||||||
} from "../../../../constants/AppConstants";
|
} from "constants/AppConstants";
|
||||||
|
import { BOTTOM_BAR_HEIGHT } from "components/BottomBar/constants";
|
||||||
|
|
||||||
const BindingContainerMaxHeight = 300;
|
const BindingContainerMaxHeight = 300;
|
||||||
const EntityHeight = 36;
|
const EntityHeight = 36;
|
||||||
const BottomBarHeight = 34;
|
|
||||||
|
|
||||||
const EntityInfoContainer = styled.div`
|
const EntityInfoContainer = styled.div`
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
|
|
@ -108,7 +108,7 @@ export function EntityProperties() {
|
||||||
let bottom;
|
let bottom;
|
||||||
if (
|
if (
|
||||||
top + BindingContainerMaxHeight >
|
top + BindingContainerMaxHeight >
|
||||||
window.innerHeight - BottomBarHeight
|
window.innerHeight - BOTTOM_BAR_HEIGHT
|
||||||
) {
|
) {
|
||||||
bottom = window.innerHeight - rect?.bottom - EntityHeight;
|
bottom = window.innerHeight - rect?.bottom - EntityHeight;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,14 @@ import { QueryEditor } from "./Query";
|
||||||
import EditorTabs from "../EditorTabs";
|
import EditorTabs from "../EditorTabs";
|
||||||
import { useCurrentEditorState } from "../hooks";
|
import { useCurrentEditorState } from "../hooks";
|
||||||
import { EditorEntityTab } from "ee/entities/IDE/constants";
|
import { EditorEntityTab } from "ee/entities/IDE/constants";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
const Container = styled(Flex)`
|
||||||
|
// Animating using https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API
|
||||||
|
& {
|
||||||
|
view-transition-name: editor-pane;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const Editor = () => {
|
const Editor = () => {
|
||||||
const { path } = useRouteMatch();
|
const { path } = useRouteMatch();
|
||||||
|
|
@ -19,7 +27,7 @@ const Editor = () => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Container
|
||||||
className="relative"
|
className="relative"
|
||||||
flex={1}
|
flex={1}
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
|
|
@ -37,7 +45,7 @@ const Editor = () => {
|
||||||
path={querySegmentRoutes.map((route) => `${path}${route}`)}
|
path={querySegmentRoutes.map((route) => `${path}${route}`)}
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Flex>
|
</Container>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Flex } from "@appsmith/ads";
|
import { Flex } from "@appsmith/ads";
|
||||||
import { useEditorPaneWidth } from "../hooks";
|
|
||||||
import EditorPaneExplorer from "./Explorer";
|
import EditorPaneExplorer from "./Explorer";
|
||||||
import Editor from "./Editor";
|
import Editor from "./Editor";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
|
@ -9,7 +8,6 @@ import { EditorViewMode } from "ee/entities/IDE/constants";
|
||||||
import EntityProperties from "pages/Editor/Explorer/Entity/EntityProperties";
|
import EntityProperties from "pages/Editor/Explorer/Entity/EntityProperties";
|
||||||
|
|
||||||
const EditorPane = () => {
|
const EditorPane = () => {
|
||||||
const width = useEditorPaneWidth();
|
|
||||||
const ideViewMode = useSelector(getIDEViewMode);
|
const ideViewMode = useSelector(getIDEViewMode);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -26,7 +24,7 @@ const EditorPane = () => {
|
||||||
// @ts-expect-error Fix this the next time the file is edited
|
// @ts-expect-error Fix this the next time the file is edited
|
||||||
gap="spacing-2"
|
gap="spacing-2"
|
||||||
height="100%"
|
height="100%"
|
||||||
width={width}
|
width={"100%"}
|
||||||
>
|
>
|
||||||
{/** Entity Properties component is necessary to render
|
{/** Entity Properties component is necessary to render
|
||||||
the Bindings popover in the context menu.
|
the Bindings popover in the context menu.
|
||||||
|
|
|
||||||
|
|
@ -11,24 +11,48 @@ import {
|
||||||
createMessage,
|
createMessage,
|
||||||
} from "ee/constants/messages";
|
} from "ee/constants/messages";
|
||||||
import { setIdeEditorViewMode } from "actions/ideActions";
|
import { setIdeEditorViewMode } from "actions/ideActions";
|
||||||
|
import type { AppState } from "ee/reducers";
|
||||||
|
import { selectFeatureFlagCheck } from "ee/selectors/featureFlagsSelectors";
|
||||||
|
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
|
||||||
|
|
||||||
export const ScreenModeToggle = () => {
|
export const ScreenModeToggle = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const ideViewMode = useSelector(getIDEViewMode);
|
const ideViewMode = useSelector(getIDEViewMode);
|
||||||
|
const isAnimatedIDEEnabled = useSelector((state: AppState) => {
|
||||||
|
return selectFeatureFlagCheck(
|
||||||
|
state,
|
||||||
|
FEATURE_FLAG.release_ide_animations_enabled,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const switchToFullScreen = useCallback(() => {
|
const switchToFullScreen = useCallback(() => {
|
||||||
AnalyticsUtil.logEvent("EDITOR_MODE_CHANGE", {
|
AnalyticsUtil.logEvent("EDITOR_MODE_CHANGE", {
|
||||||
to: EditorViewMode.FullScreen,
|
to: EditorViewMode.FullScreen,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Animating using https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API
|
||||||
|
// this has limited availability right now
|
||||||
|
if ("startViewTransition" in document && isAnimatedIDEEnabled) {
|
||||||
|
document.startViewTransition(() => {
|
||||||
dispatch(setIdeEditorViewMode(EditorViewMode.FullScreen));
|
dispatch(setIdeEditorViewMode(EditorViewMode.FullScreen));
|
||||||
}, [dispatch]);
|
});
|
||||||
|
} else {
|
||||||
|
dispatch(setIdeEditorViewMode(EditorViewMode.FullScreen));
|
||||||
|
}
|
||||||
|
}, [dispatch, isAnimatedIDEEnabled]);
|
||||||
|
|
||||||
const switchToSplitScreen = useCallback(() => {
|
const switchToSplitScreen = useCallback(() => {
|
||||||
AnalyticsUtil.logEvent("EDITOR_MODE_CHANGE", {
|
AnalyticsUtil.logEvent("EDITOR_MODE_CHANGE", {
|
||||||
to: EditorViewMode.SplitScreen,
|
to: EditorViewMode.SplitScreen,
|
||||||
});
|
});
|
||||||
|
if ("startViewTransition" in document && isAnimatedIDEEnabled) {
|
||||||
|
document.startViewTransition(() => {
|
||||||
dispatch(setIdeEditorViewMode(EditorViewMode.SplitScreen));
|
dispatch(setIdeEditorViewMode(EditorViewMode.SplitScreen));
|
||||||
}, [dispatch]);
|
});
|
||||||
|
} else {
|
||||||
|
dispatch(setIdeEditorViewMode(EditorViewMode.SplitScreen));
|
||||||
|
}
|
||||||
|
}, [dispatch, isAnimatedIDEEnabled]);
|
||||||
|
|
||||||
if (ideViewMode === EditorViewMode.SplitScreen) {
|
if (ideViewMode === EditorViewMode.SplitScreen) {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
51
app/client/src/pages/Editor/IDE/Layout/AnimatedLayout.tsx
Normal file
51
app/client/src/pages/Editor/IDE/Layout/AnimatedLayout.tsx
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import React from "react";
|
||||||
|
import { useGridLayoutTemplate } from "./hooks/useGridLayoutTemplate";
|
||||||
|
import EditorWrapperContainer from "pages/Editor/commons/EditorWrapperContainer";
|
||||||
|
import { AnimatedGridLayout, LayoutArea } from "components/AnimatedGridLayout";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import BottomBar from "components/BottomBar";
|
||||||
|
import Sidebar from "../Sidebar";
|
||||||
|
import LeftPane from "../LeftPane";
|
||||||
|
import MainPane from "../MainPane";
|
||||||
|
import RightPane from "../RightPane";
|
||||||
|
import { Areas } from "./constants";
|
||||||
|
import ProtectedCallout from "../ProtectedCallout";
|
||||||
|
import { protectedModeSelector } from "selectors/gitSyncSelectors";
|
||||||
|
|
||||||
|
function AnimatedLayout() {
|
||||||
|
const isProtectedMode = useSelector(protectedModeSelector);
|
||||||
|
const { areas, columns, rows } = useGridLayoutTemplate();
|
||||||
|
if (columns.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isProtectedMode && <ProtectedCallout />}
|
||||||
|
<EditorWrapperContainer>
|
||||||
|
<AnimatedGridLayout
|
||||||
|
areas={areas}
|
||||||
|
columns={columns}
|
||||||
|
height="100%"
|
||||||
|
rows={rows}
|
||||||
|
width="100vw"
|
||||||
|
>
|
||||||
|
<LayoutArea name={Areas.Sidebar}>
|
||||||
|
<Sidebar />
|
||||||
|
</LayoutArea>
|
||||||
|
<LayoutArea name={Areas.Explorer}>
|
||||||
|
<LeftPane />
|
||||||
|
</LayoutArea>
|
||||||
|
<LayoutArea name={Areas.WidgetEditor}>
|
||||||
|
<MainPane id="app-body" />
|
||||||
|
</LayoutArea>
|
||||||
|
<LayoutArea name={Areas.PropertyPane}>
|
||||||
|
<RightPane />
|
||||||
|
</LayoutArea>
|
||||||
|
</AnimatedGridLayout>
|
||||||
|
</EditorWrapperContainer>
|
||||||
|
<BottomBar />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { AnimatedLayout };
|
||||||
67
app/client/src/pages/Editor/IDE/Layout/UnanimatedLayout.tsx
Normal file
67
app/client/src/pages/Editor/IDE/Layout/UnanimatedLayout.tsx
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
import React from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
|
import BottomBar from "components/BottomBar";
|
||||||
|
import EditorWrapperContainer from "../../commons/EditorWrapperContainer";
|
||||||
|
import Sidebar from "pages/Editor/IDE/Sidebar";
|
||||||
|
import LeftPane from "../LeftPane";
|
||||||
|
import MainPane from "../MainPane";
|
||||||
|
import RightPane from "../RightPane";
|
||||||
|
import { protectedModeSelector } from "selectors/gitSyncSelectors";
|
||||||
|
import ProtectedCallout from "../ProtectedCallout";
|
||||||
|
import { useGridLayoutTemplate } from "./hooks/useGridLayoutTemplate";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { Areas } from "./constants";
|
||||||
|
|
||||||
|
const GridContainer = styled.div`
|
||||||
|
display: grid;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const LayoutContainer = styled.div<{ name: string }>`
|
||||||
|
position: relative;
|
||||||
|
grid-area: ${(props) => props.name};
|
||||||
|
`;
|
||||||
|
|
||||||
|
function UnanimatedLayout() {
|
||||||
|
const isProtectedMode = useSelector(protectedModeSelector);
|
||||||
|
const { areas, columns } = useGridLayoutTemplate();
|
||||||
|
|
||||||
|
const isSidebarVisible = columns[0] !== "0px";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isProtectedMode && <ProtectedCallout />}
|
||||||
|
<EditorWrapperContainer>
|
||||||
|
<GridContainer
|
||||||
|
style={{
|
||||||
|
gridTemplateRows: "100%",
|
||||||
|
gridTemplateAreas: areas
|
||||||
|
.map((area) => `"${area.join(" ")}"`)
|
||||||
|
.join("\n"),
|
||||||
|
gridTemplateColumns: columns.join(" "),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LayoutContainer name={Areas.Sidebar}>
|
||||||
|
{isSidebarVisible ? <Sidebar /> : <div />}
|
||||||
|
</LayoutContainer>
|
||||||
|
<LayoutContainer name={Areas.Explorer}>
|
||||||
|
<LeftPane />
|
||||||
|
</LayoutContainer>
|
||||||
|
<LayoutContainer name={Areas.WidgetEditor}>
|
||||||
|
<MainPane id="app-body" />
|
||||||
|
</LayoutContainer>
|
||||||
|
<LayoutContainer name={Areas.PropertyPane}>
|
||||||
|
<RightPane />
|
||||||
|
</LayoutContainer>
|
||||||
|
</GridContainer>
|
||||||
|
</EditorWrapperContainer>
|
||||||
|
<BottomBar />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const MemoUanimatedLayout = React.memo(UnanimatedLayout);
|
||||||
|
|
||||||
|
export { MemoUanimatedLayout as UnanimatedLayout };
|
||||||
15
app/client/src/pages/Editor/IDE/Layout/constants.ts
Normal file
15
app/client/src/pages/Editor/IDE/Layout/constants.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { APP_SIDEBAR_WIDTH } from "constants/AppConstants";
|
||||||
|
import type { AnimatedGridUnit } from "components/AnimatedGridLayout";
|
||||||
|
|
||||||
|
export const Areas = {
|
||||||
|
Sidebar: "Sidebar",
|
||||||
|
Explorer: "Explorer",
|
||||||
|
CodeEditor: "CodeEditor",
|
||||||
|
WidgetEditor: "WidgetEditor",
|
||||||
|
PropertyPane: "PropertyPane",
|
||||||
|
BottomBar: "BottomBar",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type Area = keyof typeof Areas;
|
||||||
|
|
||||||
|
export const SIDEBAR_WIDTH = (APP_SIDEBAR_WIDTH + "px") as AnimatedGridUnit;
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
import useWindowDimensions from "utils/hooks/useWindowDimensions";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import {
|
||||||
|
APP_SIDEBAR_WIDTH,
|
||||||
|
DEFAULT_EXPLORER_PANE_WIDTH,
|
||||||
|
SPLIT_SCREEN_RATIO,
|
||||||
|
} from "constants/AppConstants";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { getIDEViewMode } from "selectors/ideSelectors";
|
||||||
|
import { getPropertyPaneWidth } from "selectors/propertyPaneSelectors";
|
||||||
|
import { EditorEntityTab, EditorViewMode } from "ee/entities/IDE/constants";
|
||||||
|
import { useCurrentEditorState } from "../../hooks";
|
||||||
|
import { previewModeSelector } from "selectors/editorSelectors";
|
||||||
|
import { protectedModeSelector } from "selectors/gitSyncSelectors";
|
||||||
|
|
||||||
|
export const useEditorStateLeftPaneWidth = (): number => {
|
||||||
|
const [windowWidth] = useWindowDimensions();
|
||||||
|
const [width, setWidth] = useState(windowWidth - APP_SIDEBAR_WIDTH);
|
||||||
|
const editorMode = useSelector(getIDEViewMode);
|
||||||
|
const { segment } = useCurrentEditorState();
|
||||||
|
const propertyPaneWidth = useSelector(getPropertyPaneWidth);
|
||||||
|
const isPreviewMode = useSelector(previewModeSelector);
|
||||||
|
const isProtectedMode = useSelector(protectedModeSelector);
|
||||||
|
useEffect(
|
||||||
|
function updateWidth() {
|
||||||
|
if (isPreviewMode || isProtectedMode) {
|
||||||
|
setWidth(0);
|
||||||
|
} else if (segment !== EditorEntityTab.UI) {
|
||||||
|
if (editorMode === EditorViewMode.SplitScreen) {
|
||||||
|
setWidth(windowWidth * SPLIT_SCREEN_RATIO);
|
||||||
|
} else {
|
||||||
|
setWidth(windowWidth - APP_SIDEBAR_WIDTH);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setWidth(DEFAULT_EXPLORER_PANE_WIDTH);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
editorMode,
|
||||||
|
segment,
|
||||||
|
propertyPaneWidth,
|
||||||
|
windowWidth,
|
||||||
|
isPreviewMode,
|
||||||
|
isProtectedMode,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return width;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
import React from "react";
|
||||||
|
import type { AnimatedGridUnit } from "components/AnimatedGridLayout";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import useWindowDimensions from "utils/hooks/useWindowDimensions";
|
||||||
|
import { useCurrentAppState, useCurrentEditorState } from "../../hooks";
|
||||||
|
import { getPropertyPaneWidth } from "selectors/propertyPaneSelectors";
|
||||||
|
import { previewModeSelector } from "selectors/editorSelectors";
|
||||||
|
import { getIDEViewMode } from "selectors/ideSelectors";
|
||||||
|
import { protectedModeSelector } from "selectors/gitSyncSelectors";
|
||||||
|
import {
|
||||||
|
EditorEntityTab,
|
||||||
|
EditorState,
|
||||||
|
EditorViewMode,
|
||||||
|
} from "ee/entities/IDE/constants";
|
||||||
|
import {
|
||||||
|
APP_SETTINGS_PANE_WIDTH,
|
||||||
|
APP_SIDEBAR_WIDTH,
|
||||||
|
} from "constants/AppConstants";
|
||||||
|
import { useEditorStateLeftPaneWidth } from "./useEditorStateLeftPaneWidth";
|
||||||
|
import { type Area, Areas, SIDEBAR_WIDTH } from "../constants";
|
||||||
|
|
||||||
|
interface ReturnValue {
|
||||||
|
areas: Area[][];
|
||||||
|
rows: AnimatedGridUnit[];
|
||||||
|
columns: AnimatedGridUnit[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function useGridLayoutTemplate(): ReturnValue {
|
||||||
|
const areas = React.useMemo(function initialiseAreas() {
|
||||||
|
return [
|
||||||
|
[Areas.Sidebar, Areas.Explorer, Areas.WidgetEditor, Areas.PropertyPane],
|
||||||
|
];
|
||||||
|
}, []);
|
||||||
|
const [columns, setColumns] = React.useState<AnimatedGridUnit[]>([]);
|
||||||
|
const [rows] = React.useState<AnimatedGridUnit[]>(["1fr"]);
|
||||||
|
|
||||||
|
const [windowWidth] = useWindowDimensions();
|
||||||
|
const editorStateLeftPaneWidth = useEditorStateLeftPaneWidth();
|
||||||
|
const PropertyPaneWidth = useSelector(getPropertyPaneWidth);
|
||||||
|
const { segment } = useCurrentEditorState();
|
||||||
|
const appState = useCurrentAppState();
|
||||||
|
const isPreviewMode = useSelector(previewModeSelector);
|
||||||
|
const editorMode = useSelector(getIDEViewMode);
|
||||||
|
const isProtectedMode = useSelector(protectedModeSelector);
|
||||||
|
|
||||||
|
React.useEffect(
|
||||||
|
function updateIDEColumns() {
|
||||||
|
switch (appState) {
|
||||||
|
case EditorState.DATA:
|
||||||
|
if (isPreviewMode || isProtectedMode) {
|
||||||
|
setColumns([
|
||||||
|
"0px",
|
||||||
|
"0px",
|
||||||
|
(windowWidth + "px") as AnimatedGridUnit,
|
||||||
|
"0px",
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
setColumns([
|
||||||
|
SIDEBAR_WIDTH,
|
||||||
|
"300px",
|
||||||
|
(windowWidth - 300 - 50 + "px") as AnimatedGridUnit,
|
||||||
|
"0px",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case EditorState.SETTINGS:
|
||||||
|
if (isPreviewMode || isProtectedMode) {
|
||||||
|
setColumns([
|
||||||
|
"0px",
|
||||||
|
"0px",
|
||||||
|
(windowWidth + "px") as AnimatedGridUnit,
|
||||||
|
"0px",
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
setColumns([
|
||||||
|
SIDEBAR_WIDTH,
|
||||||
|
(APP_SETTINGS_PANE_WIDTH + "px") as AnimatedGridUnit,
|
||||||
|
(windowWidth -
|
||||||
|
APP_SIDEBAR_WIDTH -
|
||||||
|
APP_SETTINGS_PANE_WIDTH +
|
||||||
|
"px") as AnimatedGridUnit,
|
||||||
|
"0px",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EditorState.LIBRARIES:
|
||||||
|
if (isPreviewMode || isProtectedMode) {
|
||||||
|
setColumns([
|
||||||
|
"0px",
|
||||||
|
"0px",
|
||||||
|
(windowWidth + "px") as AnimatedGridUnit,
|
||||||
|
"0px",
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
setColumns([
|
||||||
|
SIDEBAR_WIDTH,
|
||||||
|
"255px",
|
||||||
|
(windowWidth -
|
||||||
|
APP_SIDEBAR_WIDTH -
|
||||||
|
255 +
|
||||||
|
"px") as AnimatedGridUnit,
|
||||||
|
"0px",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EditorState.EDITOR:
|
||||||
|
if (isPreviewMode || isProtectedMode) {
|
||||||
|
setColumns([
|
||||||
|
"0px",
|
||||||
|
(editorStateLeftPaneWidth + "px") as AnimatedGridUnit,
|
||||||
|
(windowWidth + "px") as AnimatedGridUnit,
|
||||||
|
"0px",
|
||||||
|
]);
|
||||||
|
} else if (segment !== EditorEntityTab.UI) {
|
||||||
|
if (editorMode === EditorViewMode.SplitScreen) {
|
||||||
|
setColumns([
|
||||||
|
SIDEBAR_WIDTH,
|
||||||
|
(editorStateLeftPaneWidth + "px") as AnimatedGridUnit,
|
||||||
|
(windowWidth -
|
||||||
|
APP_SIDEBAR_WIDTH -
|
||||||
|
editorStateLeftPaneWidth +
|
||||||
|
"px") as AnimatedGridUnit,
|
||||||
|
"0px",
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
setColumns([
|
||||||
|
SIDEBAR_WIDTH,
|
||||||
|
(editorStateLeftPaneWidth + "px") as AnimatedGridUnit,
|
||||||
|
"0px",
|
||||||
|
"0px",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setColumns([
|
||||||
|
SIDEBAR_WIDTH,
|
||||||
|
(editorStateLeftPaneWidth + "px") as AnimatedGridUnit,
|
||||||
|
(windowWidth -
|
||||||
|
APP_SIDEBAR_WIDTH -
|
||||||
|
editorStateLeftPaneWidth -
|
||||||
|
PropertyPaneWidth +
|
||||||
|
1 +
|
||||||
|
"px") as AnimatedGridUnit,
|
||||||
|
(PropertyPaneWidth + 1 + "px") as AnimatedGridUnit,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
appState,
|
||||||
|
isPreviewMode,
|
||||||
|
isProtectedMode,
|
||||||
|
editorStateLeftPaneWidth,
|
||||||
|
PropertyPaneWidth,
|
||||||
|
segment,
|
||||||
|
editorMode,
|
||||||
|
windowWidth,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { areas, columns, rows };
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useGridLayoutTemplate };
|
||||||
2
app/client/src/pages/Editor/IDE/Layout/index.ts
Normal file
2
app/client/src/pages/Editor/IDE/Layout/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { AnimatedLayout } from "./AnimatedLayout";
|
||||||
|
export { UnanimatedLayout } from "./UnanimatedLayout";
|
||||||
|
|
@ -98,7 +98,7 @@ const DataSidePane = (props: DataSidePaneProps) => {
|
||||||
borderRight="1px solid var(--ads-v2-color-border)"
|
borderRight="1px solid var(--ads-v2-color-border)"
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
height="100%"
|
height="100%"
|
||||||
width="300px"
|
width="100%"
|
||||||
>
|
>
|
||||||
<PaneHeader
|
<PaneHeader
|
||||||
rightIcon={
|
rightIcon={
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import { selectLibrariesForExplorer } from "ee/selectors/entitiesSelector";
|
||||||
import { animated, useTransition } from "react-spring";
|
import { animated, useTransition } from "react-spring";
|
||||||
import { LibraryEntity } from "pages/Editor/Explorer/Libraries";
|
import { LibraryEntity } from "pages/Editor/Explorer/Libraries";
|
||||||
import { Flex } from "@appsmith/ads";
|
import { Flex } from "@appsmith/ads";
|
||||||
import { DEFAULT_EXPLORER_PANE_WIDTH } from "constants/AppConstants";
|
|
||||||
|
|
||||||
const LibrarySidePane = () => {
|
const LibrarySidePane = () => {
|
||||||
const libraries = useSelector(selectLibrariesForExplorer);
|
const libraries = useSelector(selectLibrariesForExplorer);
|
||||||
|
|
@ -21,7 +20,7 @@ const LibrarySidePane = () => {
|
||||||
borderRight="1px solid var(--ads-v2-color-border)"
|
borderRight="1px solid var(--ads-v2-color-border)"
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
height="100%"
|
height="100%"
|
||||||
width={DEFAULT_EXPLORER_PANE_WIDTH + "px"}
|
width={"100%"}
|
||||||
>
|
>
|
||||||
<PaneHeader
|
<PaneHeader
|
||||||
rightIcon={<AddLibraryPopover />}
|
rightIcon={<AddLibraryPopover />}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ export const LeftPaneContainer = styled.div<{ showRightBorder?: boolean }>`
|
||||||
border-right: ${({ showRightBorder = true }) =>
|
border-right: ${({ showRightBorder = true }) =>
|
||||||
showRightBorder ? "1px solid var(--ads-v2-color-border)" : "none"};
|
showRightBorder ? "1px solid var(--ads-v2-color-border)" : "none"};
|
||||||
background: var(--ads-v2-color-bg);
|
background: var(--ads-v2-color-bg);
|
||||||
|
overflow: hidden;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const LeftPane = () => {
|
const LeftPane = () => {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export const MainPane = (props: { id: string }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative flex flex-col flex-1 overflow-auto z-2"
|
className="relative flex flex-col flex-1 overflow-auto z-2 h-full"
|
||||||
data-testid="t--ide-main-pane"
|
data-testid="t--ide-main-pane"
|
||||||
id={props.id}
|
id={props.id}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,15 @@ import IDE from ".";
|
||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import "@testing-library/jest-dom";
|
import "@testing-library/jest-dom";
|
||||||
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
||||||
|
import store from "store";
|
||||||
|
|
||||||
// TODO: Fix this the next time the file is edited
|
// TODO: Fix this the next time the file is edited
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const getMockStore = (override: Record<string, any> = {}): any => {
|
const getMockStore = (override: Record<string, any> = {}): any => {
|
||||||
|
const initialState = store.getState();
|
||||||
const slice = {
|
const slice = {
|
||||||
ui: {
|
ui: {
|
||||||
|
...initialState.ui,
|
||||||
applications: {
|
applications: {
|
||||||
currentApplication: {
|
currentApplication: {
|
||||||
gitApplicationMetadata: {
|
gitApplicationMetadata: {
|
||||||
|
|
@ -32,6 +35,7 @@ const getMockStore = (override: Record<string, any> = {}): any => {
|
||||||
const mockStore = configureStore([]);
|
const mockStore = configureStore([]);
|
||||||
const newSlice = merge(slice, override);
|
const newSlice = merge(slice, override);
|
||||||
return mockStore({
|
return mockStore({
|
||||||
|
...initialState,
|
||||||
...newSlice,
|
...newSlice,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@ import {
|
||||||
createMessage,
|
createMessage,
|
||||||
} from "ee/constants/messages";
|
} from "ee/constants/messages";
|
||||||
|
|
||||||
|
export const PROTECTED_CALLOUT_HEIGHT = 70;
|
||||||
|
|
||||||
const StyledCallout = styled(Callout)`
|
const StyledCallout = styled(Callout)`
|
||||||
height: 70px;
|
height: ${PROTECTED_CALLOUT_HEIGHT}px;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,10 @@ import {
|
||||||
EditorEntityTab,
|
EditorEntityTab,
|
||||||
EditorEntityTabState,
|
EditorEntityTabState,
|
||||||
EditorState,
|
EditorState,
|
||||||
EditorViewMode,
|
|
||||||
} from "ee/entities/IDE/constants";
|
} from "ee/entities/IDE/constants";
|
||||||
import { useLocation } from "react-router";
|
import { useLocation } from "react-router";
|
||||||
import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity";
|
import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { getIDEViewMode } from "selectors/ideSelectors";
|
|
||||||
import { getPropertyPaneWidth } from "selectors/propertyPaneSelectors";
|
|
||||||
import history, { NavigationMethod } from "utils/history";
|
import history, { NavigationMethod } from "utils/history";
|
||||||
import {
|
import {
|
||||||
builderURL,
|
builderURL,
|
||||||
|
|
@ -20,11 +17,6 @@ import {
|
||||||
} from "ee/RouteBuilder";
|
} from "ee/RouteBuilder";
|
||||||
import { getCurrentFocusInfo } from "selectors/focusHistorySelectors";
|
import { getCurrentFocusInfo } from "selectors/focusHistorySelectors";
|
||||||
import { getCurrentGitBranch } from "selectors/gitSyncSelectors";
|
import { getCurrentGitBranch } from "selectors/gitSyncSelectors";
|
||||||
import {
|
|
||||||
APP_SIDEBAR_WIDTH,
|
|
||||||
DEFAULT_EXPLORER_PANE_WIDTH,
|
|
||||||
SPLIT_SCREEN_RATIO,
|
|
||||||
} from "constants/AppConstants";
|
|
||||||
import { getIsAltFocusWidget, getWidgetSelectionBlock } from "selectors/ui";
|
import { getIsAltFocusWidget, getWidgetSelectionBlock } from "selectors/ui";
|
||||||
import { altFocusWidget, setWidgetSelectionBlock } from "actions/widgetActions";
|
import { altFocusWidget, setWidgetSelectionBlock } from "actions/widgetActions";
|
||||||
import { useJSAdd } from "ee/pages/Editor/IDE/EditorPane/JS/hooks";
|
import { useJSAdd } from "ee/pages/Editor/IDE/EditorPane/JS/hooks";
|
||||||
|
|
@ -36,7 +28,6 @@ import { closeJSActionTab } from "actions/jsActionActions";
|
||||||
import { closeQueryActionTab } from "actions/pluginActionActions";
|
import { closeQueryActionTab } from "actions/pluginActionActions";
|
||||||
import { getCurrentBasePageId } from "selectors/editorSelectors";
|
import { getCurrentBasePageId } from "selectors/editorSelectors";
|
||||||
import { getCurrentEntityInfo } from "../utils";
|
import { getCurrentEntityInfo } from "../utils";
|
||||||
import useWindowDimensions from "../../../utils/hooks/useWindowDimensions";
|
|
||||||
|
|
||||||
export const useCurrentAppState = () => {
|
export const useCurrentAppState = () => {
|
||||||
const [appState, setAppState] = useState(EditorState.EDITOR);
|
const [appState, setAppState] = useState(EditorState.EDITOR);
|
||||||
|
|
@ -75,32 +66,6 @@ export const useCurrentEditorState = () => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useEditorPaneWidth = (): string => {
|
|
||||||
const [windowWidth] = useWindowDimensions();
|
|
||||||
const [width, setWidth] = useState(windowWidth - APP_SIDEBAR_WIDTH + "px");
|
|
||||||
const editorMode = useSelector(getIDEViewMode);
|
|
||||||
const { segment } = useCurrentEditorState();
|
|
||||||
const propertyPaneWidth = useSelector(getPropertyPaneWidth);
|
|
||||||
useEffect(() => {
|
|
||||||
if (editorMode === EditorViewMode.SplitScreen) {
|
|
||||||
if (segment !== EditorEntityTab.UI) {
|
|
||||||
// 1px is propertypane border width
|
|
||||||
setWidth(windowWidth * SPLIT_SCREEN_RATIO + "px");
|
|
||||||
} else {
|
|
||||||
setWidth(DEFAULT_EXPLORER_PANE_WIDTH + "px");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (segment !== EditorEntityTab.UI) {
|
|
||||||
setWidth(windowWidth - APP_SIDEBAR_WIDTH + "px");
|
|
||||||
} else {
|
|
||||||
setWidth(DEFAULT_EXPLORER_PANE_WIDTH + "px");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [editorMode, segment, propertyPaneWidth, windowWidth]);
|
|
||||||
|
|
||||||
return width;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useSegmentNavigation = (): {
|
export const useSegmentNavigation = (): {
|
||||||
onSegmentChange: (value: string) => void;
|
onSegmentChange: (value: string) => void;
|
||||||
} => {
|
} => {
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,28 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { selectFeatureFlagCheck } from "ee/selectors/featureFlagsSelectors";
|
||||||
|
import { AnimatedLayout, UnanimatedLayout } from "./Layout";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
import type { AppState } from "ee/reducers";
|
||||||
|
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
|
||||||
|
|
||||||
import BottomBar from "components/BottomBar";
|
const checkAnimatedIDEFlagValue = (state: AppState) => {
|
||||||
import {
|
return selectFeatureFlagCheck(
|
||||||
combinedPreviewModeSelector,
|
state,
|
||||||
previewModeSelector,
|
FEATURE_FLAG.release_ide_animations_enabled,
|
||||||
} from "selectors/editorSelectors";
|
);
|
||||||
import EditorWrapperContainer from "../commons/EditorWrapperContainer";
|
};
|
||||||
import Sidebar from "pages/Editor/IDE/Sidebar";
|
|
||||||
import LeftPane from "./LeftPane";
|
|
||||||
import MainPane from "./MainPane";
|
|
||||||
import RightPane from "./RightPane";
|
|
||||||
import classNames from "classnames";
|
|
||||||
import { tailwindLayers } from "constants/Layers";
|
|
||||||
import { protectedModeSelector } from "selectors/gitSyncSelectors";
|
|
||||||
import ProtectedCallout from "./ProtectedCallout";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OldName: MainContainer
|
* OldName: MainContainer
|
||||||
*/
|
*/
|
||||||
function IDE() {
|
function IDE() {
|
||||||
const isPreviewMode = useSelector(previewModeSelector);
|
const isAnimatedIDEEnabled = useSelector(checkAnimatedIDEFlagValue);
|
||||||
const isCombinedPreviewMode = useSelector(combinedPreviewModeSelector);
|
if (isAnimatedIDEEnabled) {
|
||||||
const isProtectedMode = useSelector(protectedModeSelector);
|
return <AnimatedLayout />;
|
||||||
|
}
|
||||||
return (
|
return <UnanimatedLayout />;
|
||||||
<>
|
|
||||||
{isProtectedMode && <ProtectedCallout />}
|
|
||||||
<EditorWrapperContainer>
|
|
||||||
<div
|
|
||||||
className={classNames({
|
|
||||||
[`transition-transform transform duration-400 flex h-full ${tailwindLayers.entityExplorer}`]:
|
|
||||||
true,
|
|
||||||
relative: !isCombinedPreviewMode,
|
|
||||||
"-translate-x-full fixed": isCombinedPreviewMode,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Sidebar />
|
|
||||||
<LeftPane />
|
|
||||||
</div>
|
|
||||||
<MainPane id="app-body" />
|
|
||||||
<div
|
|
||||||
className={classNames({
|
|
||||||
[`transition-transform transform duration-400 h-full ${tailwindLayers.propertyPane}`]:
|
|
||||||
true,
|
|
||||||
relative: !isCombinedPreviewMode,
|
|
||||||
"translate-x-full fixed right-0": isCombinedPreviewMode,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<RightPane />
|
|
||||||
</div>
|
|
||||||
</EditorWrapperContainer>
|
|
||||||
<BottomBar viewMode={isPreviewMode} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IDE.displayName = "AppsmithIDE";
|
IDE.displayName = "AppIDE";
|
||||||
|
|
||||||
export default React.memo(IDE);
|
export default React.memo(IDE);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import {
|
||||||
RUN_GUTTER_ID,
|
RUN_GUTTER_ID,
|
||||||
} from "./constants";
|
} from "./constants";
|
||||||
import { thinScrollbar } from "constants/DefaultTheme";
|
import { thinScrollbar } from "constants/DefaultTheme";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "IDE";
|
||||||
|
|
||||||
export const CodeEditorWithGutterStyles = css`
|
export const CodeEditorWithGutterStyles = css`
|
||||||
.${RUN_GUTTER_ID} {
|
.${RUN_GUTTER_ID} {
|
||||||
|
|
@ -31,7 +32,7 @@ export const CodeEditorWithGutterStyles = css`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const FormWrapper = styled.div`
|
export const FormWrapper = styled.div`
|
||||||
height: ${({ theme }) => `calc(100vh - ${theme.smallHeaderHeight})`};
|
height: calc(100vh - ${IDE_HEADER_HEIGHT}px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
.${JS_OBJECT_HOTKEYS_CLASSNAME} {
|
.${JS_OBJECT_HOTKEYS_CLASSNAME} {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,10 @@ import useInteractionAnalyticsEvent from "utils/hooks/useInteractionAnalyticsEve
|
||||||
|
|
||||||
import type { WidgetType } from "constants/WidgetConstants";
|
import type { WidgetType } from "constants/WidgetConstants";
|
||||||
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
||||||
import { getIsCurrentWidgetRecentlyAdded } from "selectors/propertyPaneSelectors";
|
import {
|
||||||
|
getIsCurrentWidgetRecentlyAdded,
|
||||||
|
getPropertyPaneWidth,
|
||||||
|
} from "selectors/propertyPaneSelectors";
|
||||||
|
|
||||||
interface PropertyPaneTitleProps {
|
interface PropertyPaneTitleProps {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -63,6 +66,7 @@ const PropertyPaneTitle = memo(function PropertyPaneTitle(
|
||||||
const isCurrentWidgetRecentlyAdded = useSelector(
|
const isCurrentWidgetRecentlyAdded = useSelector(
|
||||||
getIsCurrentWidgetRecentlyAdded,
|
getIsCurrentWidgetRecentlyAdded,
|
||||||
);
|
);
|
||||||
|
const width = useSelector(getPropertyPaneWidth);
|
||||||
|
|
||||||
const { dispatchInteractionAnalyticsEvent, eventEmitterRef } =
|
const { dispatchInteractionAnalyticsEvent, eventEmitterRef } =
|
||||||
useInteractionAnalyticsEvent<HTMLDivElement>();
|
useInteractionAnalyticsEvent<HTMLDivElement>();
|
||||||
|
|
@ -160,8 +164,9 @@ const PropertyPaneTitle = memo(function PropertyPaneTitle(
|
||||||
|
|
||||||
return props.widgetId || props.isPanelTitle ? (
|
return props.widgetId || props.isPanelTitle ? (
|
||||||
<div
|
<div
|
||||||
className="flex items-center w-full px-4 py-3 space-x-1 fixed bg-white z-3"
|
className="flex items-center px-4 py-3 space-x-1 fixed bg-white z-3"
|
||||||
ref={eventEmitterRef}
|
ref={eventEmitterRef}
|
||||||
|
style={{ width: width + "px" }}
|
||||||
>
|
>
|
||||||
{/* BACK BUTTON */}
|
{/* BACK BUTTON */}
|
||||||
{props.isPanelTitle && (
|
{props.isPanelTitle && (
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,13 @@ import { useSelector } from "react-redux";
|
||||||
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
|
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
|
||||||
import { EditorState } from "ee/entities/IDE/constants";
|
import { EditorState } from "ee/entities/IDE/constants";
|
||||||
import { RenderModes } from "constants/WidgetConstants";
|
import { RenderModes } from "constants/WidgetConstants";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "IDE";
|
||||||
|
import { BOTTOM_BAR_HEIGHT } from "components/BottomBar/constants";
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
height: calc(100vh - ${IDE_HEADER_HEIGHT} - ${BOTTOM_BAR_HEIGHT});
|
||||||
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WidgetEditorContainer
|
* WidgetEditorContainer
|
||||||
|
|
@ -21,7 +28,7 @@ export const WidgetEditorContainer = (props: { children: ReactNode }) => {
|
||||||
appState === EditorState.SETTINGS && isNavigationSelectedInSettings;
|
appState === EditorState.SETTINGS && isNavigationSelectedInSettings;
|
||||||
return (
|
return (
|
||||||
<EditorContextProvider renderMode={RenderModes.CANVAS}>
|
<EditorContextProvider renderMode={RenderModes.CANVAS}>
|
||||||
<div className="relative flex flex-row h-full w-full overflow-hidden">
|
<Container className="relative flex flex-row h-full w-full overflow-hidden">
|
||||||
<div
|
<div
|
||||||
className={classNames({
|
className={classNames({
|
||||||
"relative flex flex-col w-full overflow-hidden": true,
|
"relative flex flex-col w-full overflow-hidden": true,
|
||||||
|
|
@ -31,7 +38,7 @@ export const WidgetEditorContainer = (props: { children: ReactNode }) => {
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Container>
|
||||||
</EditorContextProvider>
|
</EditorContextProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
import { setPropertyPaneWidthAction } from "actions/propertyPaneActions";
|
import React from "react";
|
||||||
import PropertyPaneSidebar from "components/editorComponents/PropertyPaneSidebar";
|
import PropertyPaneSidebar from "components/editorComponents/PropertyPaneSidebar";
|
||||||
import React, { useCallback } from "react";
|
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
|
||||||
import { getPropertyPaneWidth } from "selectors/propertyPaneSelectors";
|
|
||||||
import { CreateNewQueryModal } from "pages/Editor/IDE/RightPane/components/CreateNewQueryModal";
|
import { CreateNewQueryModal } from "pages/Editor/IDE/RightPane/components/CreateNewQueryModal";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -12,32 +9,9 @@ import { CreateNewQueryModal } from "pages/Editor/IDE/RightPane/components/Creat
|
||||||
* It is used to handle the width of the property pane sidebar.
|
* It is used to handle the width of the property pane sidebar.
|
||||||
*/
|
*/
|
||||||
function PropertyPaneWrapper() {
|
function PropertyPaneWrapper() {
|
||||||
const dispatch = useDispatch();
|
|
||||||
const propertyPaneWidth = useSelector(getPropertyPaneWidth);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* on property pane sidebar drag end
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
const onRightSidebarDragEnd = useCallback(() => {
|
|
||||||
dispatch(setPropertyPaneWidthAction(propertyPaneWidth));
|
|
||||||
}, [propertyPaneWidth]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* on property pane sidebar width change
|
|
||||||
*/
|
|
||||||
const onRightSidebarWidthChange = useCallback((newWidth) => {
|
|
||||||
dispatch(setPropertyPaneWidthAction(newWidth));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PropertyPaneSidebar
|
<PropertyPaneSidebar />
|
||||||
onDragEnd={onRightSidebarDragEnd}
|
|
||||||
onWidthChange={onRightSidebarWidthChange}
|
|
||||||
width={propertyPaneWidth}
|
|
||||||
/>
|
|
||||||
<CreateNewQueryModal />
|
<CreateNewQueryModal />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Profile } from "pages/common/ProfileImage";
|
import { Profile } from "pages/common/ProfileImage";
|
||||||
import { getTypographyByKey } from "@appsmith/ads-old";
|
import { getTypographyByKey } from "@appsmith/ads-old";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "IDE";
|
||||||
|
|
||||||
export const HeaderWrapper = styled.div`
|
export const HeaderWrapper = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -10,7 +11,7 @@ export const HeaderWrapper = styled.div`
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border-bottom: 1px solid var(--ads-v2-color-border);
|
border-bottom: 1px solid var(--ads-v2-color-border);
|
||||||
height: ${(props) => props.theme.smallHeaderHeight};
|
height: ${IDE_HEADER_HEIGHT}px;
|
||||||
& .editable-application-name {
|
& .editable-application-name {
|
||||||
${getTypographyByKey("h4")}
|
${getTypographyByKey("h4")}
|
||||||
color: ${(props) => props.theme.colors.header.appName};
|
color: ${(props) => props.theme.colors.header.appName};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { APP_SETTINGS_PANE_WIDTH } from "constants/AppConstants";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import PaneHeader from "../IDE/LeftPane/PaneHeader";
|
import PaneHeader from "../IDE/LeftPane/PaneHeader";
|
||||||
|
|
@ -10,7 +9,7 @@ type EditorSettingsPaneContainerProps = React.PropsWithChildren<{
|
||||||
const SettingsPageWrapper = styled.div`
|
const SettingsPageWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: ${APP_SETTINGS_PANE_WIDTH}px;
|
width: 100%;
|
||||||
|
|
||||||
&:nth-child(2) {
|
&:nth-child(2) {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ import classNames from "classnames";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { combinedPreviewModeSelector } from "../../../selectors/editorSelectors";
|
import { combinedPreviewModeSelector } from "../../../selectors/editorSelectors";
|
||||||
import { protectedModeSelector } from "selectors/gitSyncSelectors";
|
import { protectedModeSelector } from "selectors/gitSyncSelectors";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "../../../IDE";
|
||||||
|
import { BOTTOM_BAR_HEIGHT } from "../../../components/BottomBar/constants";
|
||||||
|
import { PROTECTED_CALLOUT_HEIGHT } from "../IDE/ProtectedCallout";
|
||||||
|
|
||||||
interface EditorWrapperContainerProps {
|
interface EditorWrapperContainerProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
@ -14,9 +17,9 @@ const Wrapper = styled.div<{
|
||||||
}>`
|
}>`
|
||||||
display: flex;
|
display: flex;
|
||||||
height: calc(
|
height: calc(
|
||||||
100vh - ${(props) => props.theme.smallHeaderHeight} -
|
100vh - ${IDE_HEADER_HEIGHT}px - ${BOTTOM_BAR_HEIGHT}px -
|
||||||
${(props) => props.theme.bottomBarHeight} -
|
${(props) =>
|
||||||
${(props) => (props.isProtectedMode ? "70px" : "0px")}
|
props.isProtectedMode ? PROTECTED_CALLOUT_HEIGHT + "px" : "0px"}
|
||||||
);
|
);
|
||||||
background-color: ${(props) => props.theme.appBackground};
|
background-color: ${(props) => props.theme.appBackground};
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@ import styled from "styled-components";
|
||||||
import { snipingModeSelector } from "selectors/editorSelectors";
|
import { snipingModeSelector } from "selectors/editorSelectors";
|
||||||
import { retryPromise } from "utils/AppsmithUtils";
|
import { retryPromise } from "utils/AppsmithUtils";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "IDE";
|
||||||
|
|
||||||
const BindingBanner = styled.div`
|
const BindingBanner = styled.div`
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 199px;
|
width: 199px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: ${(props) => props.theme.smallHeaderHeight};
|
top: ${IDE_HEADER_HEIGHT}px;
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: var(--ads-v2-color-fg-information);
|
background: var(--ads-v2-color-fg-information);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import { Colors } from "constants/Colors";
|
||||||
import ConflictInfo from "../components/ConflictInfo";
|
import ConflictInfo from "../components/ConflictInfo";
|
||||||
import { getCurrentAppGitMetaData } from "ee/selectors/applicationSelectors";
|
import { getCurrentAppGitMetaData } from "ee/selectors/applicationSelectors";
|
||||||
import { Button } from "@appsmith/ads";
|
import { Button } from "@appsmith/ads";
|
||||||
|
import { BOTTOM_BAR_HEIGHT } from "../../../../components/BottomBar/constants";
|
||||||
|
|
||||||
const StyledGitErrorPopup = styled.div`
|
const StyledGitErrorPopup = styled.div`
|
||||||
& {
|
& {
|
||||||
|
|
@ -31,7 +32,7 @@ const StyledGitErrorPopup = styled.div`
|
||||||
.${Classes.OVERLAY_CONTENT} {
|
.${Classes.OVERLAY_CONTENT} {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
bottom: ${(props) =>
|
bottom: ${(props) =>
|
||||||
`calc(${props.theme.bottomBarHeight} + ${props.theme.spaces[3]}px)`};
|
`calc(${BOTTOM_BAR_HEIGHT}px + ${props.theme.spaces[3]}px)`};
|
||||||
left: ${(props) => props.theme.spaces[3]}px;
|
left: ${(props) => props.theme.spaces[3]}px;
|
||||||
background-color: ${Colors.WHITE};
|
background-color: ${Colors.WHITE};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ import { PartialExportModal } from "components/editorComponents/PartialImportExp
|
||||||
import { PartialImportModal } from "components/editorComponents/PartialImportExport/PartialImportModal";
|
import { PartialImportModal } from "components/editorComponents/PartialImportExport/PartialImportModal";
|
||||||
import type { Page } from "entities/Page";
|
import type { Page } from "entities/Page";
|
||||||
import { AppCURLImportModal } from "ee/pages/Editor/CurlImport";
|
import { AppCURLImportModal } from "ee/pages/Editor/CurlImport";
|
||||||
|
import { IDE_HEADER_HEIGHT } from "IDE";
|
||||||
|
|
||||||
interface EditorProps {
|
interface EditorProps {
|
||||||
currentApplicationId?: string;
|
currentApplicationId?: string;
|
||||||
|
|
@ -175,7 +176,7 @@ class Editor extends Component<Props> {
|
||||||
if (!this.props.isEditorInitialized || this.props.loadingGuidedTour) {
|
if (!this.props.isEditorInitialized || this.props.loadingGuidedTour) {
|
||||||
return (
|
return (
|
||||||
<CenteredWrapper
|
<CenteredWrapper
|
||||||
style={{ height: `calc(100vh - ${theme.smallHeaderHeight})` }}
|
style={{ height: `calc(100vh - ${IDE_HEADER_HEIGHT}px)` }}
|
||||||
>
|
>
|
||||||
<Spinner size="lg" />
|
<Spinner size="lg" />
|
||||||
</CenteredWrapper>
|
</CenteredWrapper>
|
||||||
|
|
|
||||||
|
|
@ -10631,6 +10631,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/dom-view-transitions@npm:^1.0.5":
|
||||||
|
version: 1.0.5
|
||||||
|
resolution: "@types/dom-view-transitions@npm:1.0.5"
|
||||||
|
checksum: 4190915a3d4c63d4c590d5e64d14ca1d1140496a75adb5af64b0ef13e075cc7676bff926f5c5c60305c4f6d46965a196c119a7960cbe0ff40e95e17e82334c22
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/dom4@npm:^2.0.1":
|
"@types/dom4@npm:^2.0.1":
|
||||||
version: 2.0.2
|
version: 2.0.2
|
||||||
resolution: "@types/dom4@npm:2.0.2"
|
resolution: "@types/dom4@npm:2.0.2"
|
||||||
|
|
@ -13214,6 +13221,7 @@ __metadata:
|
||||||
"@types/d3-geo": ^3.1.0
|
"@types/d3-geo": ^3.1.0
|
||||||
"@types/deep-diff": ^1.0.0
|
"@types/deep-diff": ^1.0.0
|
||||||
"@types/dom-mediacapture-record": ^1.0.11
|
"@types/dom-mediacapture-record": ^1.0.11
|
||||||
|
"@types/dom-view-transitions": ^1.0.5
|
||||||
"@types/downloadjs": ^1.4.2
|
"@types/downloadjs": ^1.4.2
|
||||||
"@types/google.maps": ^3.51.0
|
"@types/google.maps": ^3.51.0
|
||||||
"@types/jest": ^27.4.1
|
"@types/jest": ^27.4.1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user