diff --git a/app/client/src/assets/icons/ads/down-arrow.svg b/app/client/src/assets/icons/ads/down-arrow.svg new file mode 100644 index 0000000000..dd7304be3b --- /dev/null +++ b/app/client/src/assets/icons/ads/down-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/client/src/assets/icons/ads/git-branch.svg b/app/client/src/assets/icons/ads/git-branch.svg new file mode 100644 index 0000000000..9270a3d651 --- /dev/null +++ b/app/client/src/assets/icons/ads/git-branch.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/client/src/assets/icons/ads/plus.svg b/app/client/src/assets/icons/ads/plus.svg new file mode 100644 index 0000000000..16f0cfa45a --- /dev/null +++ b/app/client/src/assets/icons/ads/plus.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/client/src/assets/icons/ads/up-arrow.svg b/app/client/src/assets/icons/ads/up-arrow.svg new file mode 100644 index 0000000000..7845a77b0b --- /dev/null +++ b/app/client/src/assets/icons/ads/up-arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/client/src/components/editorComponents/Debugger/DebuggerTabs.tsx b/app/client/src/components/editorComponents/Debugger/DebuggerTabs.tsx index a541ee2cbb..12529306ec 100644 --- a/app/client/src/components/editorComponents/Debugger/DebuggerTabs.tsx +++ b/app/client/src/components/editorComponents/Debugger/DebuggerTabs.tsx @@ -21,7 +21,7 @@ const TABS_HEADER_HEIGHT = 36; const Container = styled.div` ${ResizerCSS} - position: fixed; + position: absolute; bottom: 0; height: 25%; min-height: ${TABS_HEADER_HEIGHT}px; diff --git a/app/client/src/components/editorComponents/Debugger/index.tsx b/app/client/src/components/editorComponents/Debugger/index.tsx index e1bf67b241..16e599eb18 100644 --- a/app/client/src/components/editorComponents/Debugger/index.tsx +++ b/app/client/src/components/editorComponents/Debugger/index.tsx @@ -18,7 +18,7 @@ const Container = styled.div<{ errorCount: number; warningCount: number }>` z-index: ${Layers.debugger}; background-color: ${(props) => props.theme.colors.debugger.floatingButton.background}; - position: fixed; + position: absolute; right: 20px; bottom: 20px; cursor: pointer; diff --git a/app/client/src/constants/DefaultTheme.tsx b/app/client/src/constants/DefaultTheme.tsx index 7b4506ad77..1b6cbcfde2 100644 --- a/app/client/src/constants/DefaultTheme.tsx +++ b/app/client/src/constants/DefaultTheme.tsx @@ -345,6 +345,7 @@ export type Theme = { propertyPane: PropertyPaneTheme; headerHeight: string; smallHeaderHeight: string; + bottomBarHeight: string; integrationsPageUnusableHeight: string; backBanner: string; homePage: any; @@ -1197,6 +1198,15 @@ type ColorType = { menuBackgroundColor: string; separator: string; }; + editorBottomBar: { + background: string; + buttonBackgroundHover: string; + }; +}; + +const editorBottomBar = { + background: Colors.WHITE, + buttonBackgroundHover: Colors.Gallery, }; const gitSyncModal = { @@ -1405,6 +1415,7 @@ const numberedStep = { }; export const dark: ColorType = { + editorBottomBar, gitSyncModal, numberedStep, tabItemBackgroundFill, @@ -1978,6 +1989,7 @@ export const dark: ColorType = { }; export const light: ColorType = { + editorBottomBar, gitSyncModal, numberedStep, tabItemBackgroundFill, @@ -2823,6 +2835,7 @@ export const theme: Theme = { }, headerHeight: "48px", smallHeaderHeight: "35px", + bottomBarHeight: "34px", integrationsPageUnusableHeight: "182px", backBanner: "30px", canvasBottomPadding: 200, diff --git a/app/client/src/constants/Layers.tsx b/app/client/src/constants/Layers.tsx index 7489677b3f..03711f28bf 100644 --- a/app/client/src/constants/Layers.tsx +++ b/app/client/src/constants/Layers.tsx @@ -47,6 +47,7 @@ export const Layers = { contextMenu: Indices.Layer4, dynamicAutoComplete: Indices.Layer5, debugger: Indices.Layer6, + bottomBar: Indices.Layer6, productUpdates: Indices.Layer7, portals: Indices.Layer9, header: Indices.Layer9, diff --git a/app/client/src/constants/messages.ts b/app/client/src/constants/messages.ts index fd4c160513..666dad8e9c 100644 --- a/app/client/src/constants/messages.ts +++ b/app/client/src/constants/messages.ts @@ -462,6 +462,7 @@ export const DEPLOY_WITHOUT_GIT = () => export const DEPLOY_YOUR_APPLICATION = () => "Deploy your application"; export const COMMIT = () => "COMMIT"; export const PUSH = () => "PUSH"; +export const PULL = () => "PULL"; export const SNIPPET_DESCRIPTION = () => `Search and Insert code snippets to perform complex actions quickly.`; diff --git a/app/client/src/entities/FeatureFlag.ts b/app/client/src/entities/FeatureFlag.ts index 43bc48d3cf..70fa66f153 100644 --- a/app/client/src/entities/FeatureFlag.ts +++ b/app/client/src/entities/FeatureFlag.ts @@ -4,6 +4,7 @@ type FeatureFlag = { MULTIPLAYER: boolean; LINTING: boolean; SNIPPET: boolean; + GIT: boolean; }; export default FeatureFlag; diff --git a/app/client/src/pages/Editor/APIEditor/CurlImportForm.tsx b/app/client/src/pages/Editor/APIEditor/CurlImportForm.tsx index c0c8f93737..6b9e72d7aa 100644 --- a/app/client/src/pages/Editor/APIEditor/CurlImportForm.tsx +++ b/app/client/src/pages/Editor/APIEditor/CurlImportForm.tsx @@ -14,6 +14,11 @@ import Button from "components/editorComponents/Button"; import CurlLogo from "assets/images/Curl-logo.svg"; import CloseEditor from "../../../components/editorComponents/CloseEditor"; +const StyledForm = styled(Form)` + flex: 1; + overflow: auto; +`; + const CurlImportFormContainer = styled.div` display: flex; flex-direction: column; @@ -126,7 +131,7 @@ class CurlImportForm extends React.Component {


-
+ @@ -158,7 +163,7 @@ class CurlImportForm extends React.Component { text="Import" /> - +
); } diff --git a/app/client/src/pages/Editor/APIEditor/Form.tsx b/app/client/src/pages/Editor/APIEditor/Form.tsx index 29ebe7001e..91b4dfe257 100644 --- a/app/client/src/pages/Editor/APIEditor/Form.tsx +++ b/app/client/src/pages/Editor/APIEditor/Form.tsx @@ -56,13 +56,7 @@ import { isEmpty } from "lodash"; const Form = styled.form` display: flex; flex-direction: column; - height: calc( - 100vh - - ( - ${(props) => props.theme.smallHeaderHeight} + - ${(props) => props.theme.backBanner} - ) - ); + flex: 1; overflow: hidden; width: 100%; ${FormLabel} { diff --git a/app/client/src/pages/Editor/APIEditor/index.tsx b/app/client/src/pages/Editor/APIEditor/index.tsx index 4bc3a9ef9d..fcbe7d9c7d 100644 --- a/app/client/src/pages/Editor/APIEditor/index.tsx +++ b/app/client/src/pages/Editor/APIEditor/index.tsx @@ -186,6 +186,8 @@ class ApiEditor extends React.Component { style={{ position: "relative", height: "100%", + display: "flex", + flexDirection: "column", }} > {formUiComponent === "ApiEditorForm" && ( diff --git a/app/client/src/pages/Editor/BottomBar/index.tsx b/app/client/src/pages/Editor/BottomBar/index.tsx new file mode 100644 index 0000000000..bbd1b387b8 --- /dev/null +++ b/app/client/src/pages/Editor/BottomBar/index.tsx @@ -0,0 +1,22 @@ +import React from "react"; +import styled from "styled-components"; +import QuickGitActions from "pages/Editor/gitSync/QuickGitActions"; +import { Layers } from "constants/Layers"; + +const Container = styled.div` + position: relative; + width: 100%; + height: ${(props) => props.theme.bottomBarHeight}; + display: flex; + justify-content: space-between; + background-color: ${(props) => props.theme.colors.editorBottomBar.background}; + z-index: ${Layers.bottomBar}; +`; + +export default function BottomBar() { + return ( + + + + ); +} diff --git a/app/client/src/pages/Editor/DataSourceEditor/JSONtoForm.tsx b/app/client/src/pages/Editor/DataSourceEditor/JSONtoForm.tsx index 58e1245ddb..f08f704459 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/JSONtoForm.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/JSONtoForm.tsx @@ -50,15 +50,9 @@ export const ActionButton = styled(BaseButton)` `; const DBForm = styled.div` + flex: 1; padding: 20px; margin-right: 0px; - height: calc( - 100vh - - ( - ${(props) => props.theme.smallHeaderHeight} + - ${(props) => props.theme.backBanner} - ) - ); overflow: auto; .backBtn { padding-bottom: 1px; @@ -230,7 +224,7 @@ export class JSONtoForm< renderForm = (content: any) => { return ( -
+
{content}
diff --git a/app/client/src/pages/Editor/DataSourceEditor/RestAPIDatasourceForm.tsx b/app/client/src/pages/Editor/DataSourceEditor/RestAPIDatasourceForm.tsx index 9f0b7dd4e7..f640fc1899 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/RestAPIDatasourceForm.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/RestAPIDatasourceForm.tsx @@ -83,13 +83,10 @@ type Props = DatasourceRestApiEditorProps & InjectedFormProps; const RestApiForm = styled.div` + flex: 1; padding: 20px; margin-left: 10px; margin-right: 0px; - height: calc( - 100vh - ${(props) => props.theme.headerHeight} - - ${(props) => props.theme.backBanner} - ); overflow: auto; .backBtn { padding-bottom: 1px; diff --git a/app/client/src/pages/Editor/IntegrationEditor/ActiveDataSources.tsx b/app/client/src/pages/Editor/IntegrationEditor/ActiveDataSources.tsx index 2b395c263d..fe43514b17 100644 --- a/app/client/src/pages/Editor/IntegrationEditor/ActiveDataSources.tsx +++ b/app/client/src/pages/Editor/IntegrationEditor/ActiveDataSources.tsx @@ -16,9 +16,7 @@ const QueryHomePage = styled.div` overflow: auto; display: flex; flex-direction: column; - height: calc( - 100vh - ${(props) => props.theme.integrationsPageUnusableHeight} - ); + flex: 1; .sectionHeader { font-weight: ${(props) => props.theme.fontWeights[2]}; @@ -33,9 +31,7 @@ const CreateButton = styled(Button)` `; const EmptyActiveDatasource = styled.div` - height: calc( - 100vh - ${(props) => props.theme.integrationsPageUnusableHeight} - ); + flex: 1; display: flex; align-items: center; justify-content: center; diff --git a/app/client/src/pages/Editor/IntegrationEditor/IntegrationsHomeScreen.tsx b/app/client/src/pages/Editor/IntegrationEditor/IntegrationsHomeScreen.tsx index 9c9b77a02b..bd02020ba1 100644 --- a/app/client/src/pages/Editor/IntegrationEditor/IntegrationsHomeScreen.tsx +++ b/app/client/src/pages/Editor/IntegrationEditor/IntegrationsHomeScreen.tsx @@ -33,11 +33,13 @@ const HeaderFlex = styled.div` `; const ApiHomePage = styled.div` + display: flex; + flex-direction: column; + font-size: 20px; padding: 20px 20px 0 20px; /* margin-left: 10px; */ - min-height: calc(100vh - 66px); - max-height: calc(100vh - 66px); + flex: 1; overflow: hidden !important; .closeBtn { position: absolute; @@ -67,17 +69,16 @@ const SectionGrid = styled.div` margin-top: 16px; display: grid; grid-template-columns: 1fr 180px; + grid-template-rows: auto minmax(0, 1fr); gap: 10px 16px; + flex: 1; + min-height: 0; `; const NewIntegrationsContainer = styled.div` ${thinScrollbar}; scrollbar-width: thin; overflow: auto; - max-height: calc( - 100vh - ${(props) => props.theme.integrationsPageUnusableHeight} - ); - /* padding-bottom: 300px; */ - /* margin-top: 16px; */ + flex: 1; & > div { margin-bottom: 20px; } diff --git a/app/client/src/pages/Editor/IntegrationEditor/MockDataSources.tsx b/app/client/src/pages/Editor/IntegrationEditor/MockDataSources.tsx index b2ca53805e..fc5ec324de 100644 --- a/app/client/src/pages/Editor/IntegrationEditor/MockDataSources.tsx +++ b/app/client/src/pages/Editor/IntegrationEditor/MockDataSources.tsx @@ -15,9 +15,7 @@ const MockDataSourceWrapper = styled.div` display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; - /* height: calc( - 100vh - ${(props) => props.theme.integrationsPageUnusableHeight} - ); */ + flex: 1; .sectionHeader { font-weight: ${(props) => props.theme.fontWeights[2]}; diff --git a/app/client/src/pages/Editor/IntegrationEditor/index.tsx b/app/client/src/pages/Editor/IntegrationEditor/index.tsx index 8c13eddd37..f909e1c46e 100644 --- a/app/client/src/pages/Editor/IntegrationEditor/index.tsx +++ b/app/client/src/pages/Editor/IntegrationEditor/index.tsx @@ -16,6 +16,8 @@ const integrationsEditor = (props: Props) => { style={{ position: "relative", height: "100%", + display: "flex", + flexDirection: "column", }} > props.theme.smallHeaderHeight}); + height: calc( + 100vh - ${(props) => props.theme.smallHeaderHeight} - + ${(props) => + getFeatureFlags().GIT ? props.theme.bottomBarHeight : "0px"} + ); background-color: ${(props) => props.theme.appBackground}; `; const EditorContainer = styled.div` position: relative; width: calc(100vw - ${(props) => props.theme.sidebarWidth}); + display: flex; + flex-direction: column; `; function MainContainer() { return ( - - - - - - - - - + <> + + + + + + + + + + {getFeatureFlags().GIT && } + ); } diff --git a/app/client/src/pages/Editor/QueryEditor/EditorJSONtoForm.tsx b/app/client/src/pages/Editor/QueryEditor/EditorJSONtoForm.tsx index 0949a4f2bc..eab8099c1b 100644 --- a/app/client/src/pages/Editor/QueryEditor/EditorJSONtoForm.tsx +++ b/app/client/src/pages/Editor/QueryEditor/EditorJSONtoForm.tsx @@ -69,15 +69,12 @@ import { UIComponentTypes } from "../../../api/PluginApi"; import TooltipComponent from "components/ads/Tooltip"; const QueryFormContainer = styled.form` + flex: 1; display: flex; flex-direction: column; overflow: hidden; padding: 20px 0px 0px 0px; width: 100%; - height: calc( - 100vh - ${(props) => props.theme.smallHeaderHeight} - - ${(props) => props.theme.backBanner} - ); .statementTextArea { font-size: 14px; line-height: 20px; diff --git a/app/client/src/pages/Editor/SaaSEditor/ListView.tsx b/app/client/src/pages/Editor/SaaSEditor/ListView.tsx index 70f865d7b8..5ce6a846d4 100644 --- a/app/client/src/pages/Editor/SaaSEditor/ListView.tsx +++ b/app/client/src/pages/Editor/SaaSEditor/ListView.tsx @@ -29,7 +29,7 @@ const IntegrationHomePage = styled.div` overflow: auto; display: flex; flex-direction: column; - height: calc(100vh - ${(props) => props.theme.smallHeaderHeight}); + flex: 1; .sectionHeader { font-weight: ${(props) => props.theme.fontWeights[2]}; diff --git a/app/client/src/pages/Editor/Welcome.tsx b/app/client/src/pages/Editor/Welcome.tsx index ac1fd3ab54..8d63fd9901 100644 --- a/app/client/src/pages/Editor/Welcome.tsx +++ b/app/client/src/pages/Editor/Welcome.tsx @@ -8,7 +8,7 @@ import { AppState } from "reducers"; import { showOnboardingLoader } from "actions/onboardingActions"; const Wrapper = styled.div` - height: calc(100vh - 48px); + height: calc(100vh - ${(props) => props.theme.smallHeaderHeight}); width: 100%; display: flex; justify-content: center; diff --git a/app/client/src/pages/Editor/WidgetsEditor.tsx b/app/client/src/pages/Editor/WidgetsEditor.tsx index ffb1e5ec00..5b1b18e1ca 100644 --- a/app/client/src/pages/Editor/WidgetsEditor.tsx +++ b/app/client/src/pages/Editor/WidgetsEditor.tsx @@ -30,11 +30,12 @@ import CrudInfoModal from "./GeneratePage/components/CrudInfoModal"; const EditorWrapper = styled.div` display: flex; + flex: 1; flex-direction: column; align-items: stretch; justify-content: flex-start; overflow: hidden; - height: calc(100vh - ${(props) => props.theme.smallHeaderHeight}); + position: relative; `; const CanvasContainer = styled.section` diff --git a/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx b/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx new file mode 100644 index 0000000000..62f6e89ed6 --- /dev/null +++ b/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx @@ -0,0 +1,94 @@ +import React from "react"; +import styled from "styled-components"; +import { ReactComponent as UpArrow } from "assets/icons/ads/up-arrow.svg"; +import { ReactComponent as DownArrow } from "assets/icons/ads/down-arrow.svg"; +import { ReactComponent as Plus } from "assets/icons/ads/plus.svg"; +// import { ReactComponent as GitMerge } from "assets/icons/ads/git-merge.svg"; +import { ReactComponent as GitBranch } from "assets/icons/ads/git-branch.svg"; + +import { COMMIT, PUSH, PULL, MERGE, createMessage } from "constants/messages"; +import { noop } from "lodash"; + +type QuickActionButtonProps = { + icon: React.ReactNode; + onClick: () => void; + tooltipText: string; +}; + +const QuickActionButtonContainer = styled.div` + padding: ${(props) => props.theme.spaces[1]}px + ${(props) => props.theme.spaces[2]}px; + margin-left: ${(props) => props.theme.spaces[2]}px; + cursor: pointer; + &:hover { + background-color: ${(props) => + props.theme.colors.editorBottomBar.buttonBackgroundHover}; + } +`; + +function QuickActionButton({ + icon, + onClick, +}: // tooltipText, +QuickActionButtonProps) { + return ( + + {icon} + + ); +} + +const getQuickActionButtons = ({ + commit, + merge, + pull, + push, +}: { + commit: () => void; + push: () => void; + pull: () => void; + merge: () => void; +}) => [ + { + icon: , + onClick: commit, + tooltipText: createMessage(COMMIT), + }, + { + icon: , + onClick: push, + tooltipText: createMessage(PUSH), + }, + { + icon: , + onClick: pull, + tooltipText: createMessage(PULL), + }, + { + icon: , + onClick: merge, + tooltipText: createMessage(MERGE), + }, +]; + +const Container = styled.div` + height: 100%; + display: flex; + align-items: center; +`; + +export default function QuickGitActions() { + const quickActionButtons = getQuickActionButtons({ + commit: noop, + push: noop, + pull: noop, + merge: noop, + }); + return ( + + {quickActionButtons.map((button) => ( + + ))} + + ); +} diff --git a/app/client/src/pages/Editor/routes.tsx b/app/client/src/pages/Editor/routes.tsx index 7f87f29ad0..6eb0fc92a9 100644 --- a/app/client/src/pages/Editor/routes.tsx +++ b/app/client/src/pages/Editor/routes.tsx @@ -48,7 +48,7 @@ const Wrapper = styled.div<{ isVisible: boolean }>` top: 0; left: 0; width: ${(props) => (!props.isVisible ? "0px" : "100%")}; - height: calc(100vh - ${(props) => props.theme.smallHeaderHeight}); + height: 100%; background-color: ${(props) => props.isVisible ? "rgba(0, 0, 0, 0.26)" : "transparent"}; z-index: ${(props) => (props.isVisible ? 2 : -1)}; @@ -61,6 +61,8 @@ const DrawerWrapper = styled.div<{ background-color: white; width: ${(props) => (!props.isVisible ? "0" : "100%")}; height: 100%; + display: flex; + flex-direction: column; `; interface RouterState { diff --git a/app/client/src/pages/Editor/utils.ts b/app/client/src/pages/Editor/utils.ts index 765b69ae23..ed00dbfb48 100644 --- a/app/client/src/pages/Editor/utils.ts +++ b/app/client/src/pages/Editor/utils.ts @@ -1,6 +1,7 @@ import { debounce } from "lodash"; import ReactDOM from "react-dom"; import ResizeObserver from "resize-observer-polyfill"; +import getFeatureFlags from "utils/featureFlags"; export const draggableElement = ( id: string, @@ -38,6 +39,8 @@ export const draggableElement = ( calculatedLeft: number, calculatedTop: number, ) => { + const bottomBarOffset = getFeatureFlags().GIT ? 34 : 0; + if (calculatedLeft <= 0) { calculatedLeft = 0; } @@ -47,8 +50,12 @@ export const draggableElement = ( if (calculatedLeft >= window.innerWidth - element.clientWidth) { calculatedLeft = window.innerWidth - element.clientWidth; } - if (calculatedTop >= window.innerHeight - element.clientHeight) { - calculatedTop = window.innerHeight - element.clientHeight; + if ( + calculatedTop >= + window.innerHeight - (element.clientHeight + bottomBarOffset) + ) { + calculatedTop = + window.innerHeight - element.clientHeight - bottomBarOffset; } return { left: calculatedLeft, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagEnum.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagEnum.java index ed168ebba6..c7f8e659f9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagEnum.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/featureflags/FeatureFlagEnum.java @@ -28,6 +28,6 @@ public enum FeatureFlagEnum { COMMENT, SNIPPET, LINTING, - MULTIPLAYER; + MULTIPLAYER, + GIT; } - diff --git a/app/server/appsmith-server/src/main/resources/features/init-flags.yml b/app/server/appsmith-server/src/main/resources/features/init-flags.yml index 7a9aced20c..d76c10593e 100644 --- a/app/server/appsmith-server/src/main/resources/features/init-flags.yml +++ b/app/server/appsmith-server/src/main/resources/features/init-flags.yml @@ -53,3 +53,12 @@ ff4j: param: - name: emailDomains value: appsmith.com + + - uid: GIT + enable: true + description: Enable git for apps + flipstrategy: + class: com.appsmith.server.featureflags.strategies.EmailBasedRolloutStrategy + param: + - name: emailDomains + value: test.com