From e627da4f859e420d703e34b317366836bcc7a327 Mon Sep 17 00:00:00 2001 From: GnsP Date: Tue, 23 Apr 2024 08:25:06 +0530 Subject: [PATCH] [SCM] Minor UI updates --- app/cdap/components/FooterContext/index.ts | 41 +++++++++++++++++++ .../PullPipelineWizard.tsx | 2 +- .../LocalPipelineListView/PipelineTable.tsx | 2 +- .../LocalPipelineListView/index.tsx | 8 +++- .../OperationAlert.tsx | 22 ++++++++-- .../RemotePipelineTable.tsx | 6 ++- .../RemotePipelineListView/index.tsx | 20 ++++++--- .../SourceControlManagement/SearchBox.tsx | 2 +- .../SourceControlManagement/index.tsx | 8 +++- .../store/ActionCreator.ts | 7 ++++ .../SourceControlManagement/styles.ts | 4 +- app/cdap/main.js | 31 ++++++++++++-- app/cdap/styles/common.scss | 4 ++ 13 files changed, 135 insertions(+), 22 deletions(-) create mode 100644 app/cdap/components/FooterContext/index.ts diff --git a/app/cdap/components/FooterContext/index.ts b/app/cdap/components/FooterContext/index.ts new file mode 100644 index 00000000000..a71cc8cb24a --- /dev/null +++ b/app/cdap/components/FooterContext/index.ts @@ -0,0 +1,41 @@ +/* + * Copyright © 2024 Cask Data, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +import { createContext, useContext, useEffect } from 'react'; + +interface IFooterContext { + show: boolean; + setShow(val?: boolean): void; +} + +export const FooterContext = createContext({ + show: true, + setShow() { + return; + }, +}); + +export function useHideFooterInPage() { + const { setShow } = useContext(FooterContext); + + useEffect(() => { + setShow(false); + + return () => setShow(true); + }, []); + + return setShow; +} diff --git a/app/cdap/components/ResourceCenterEntity/PullPipelineWizard.tsx b/app/cdap/components/ResourceCenterEntity/PullPipelineWizard.tsx index 390d3c99184..0a13fabbc27 100644 --- a/app/cdap/components/ResourceCenterEntity/PullPipelineWizard.tsx +++ b/app/cdap/components/ResourceCenterEntity/PullPipelineWizard.tsx @@ -80,7 +80,7 @@ export const PullPipelineWizard = ({ isOpen, error, dispatch }: IPullPipelineWiz toggle={() => dispatch({ type: 'TOGGLE_MODAL' })} > - + diff --git a/app/cdap/components/SourceControlManagement/LocalPipelineListView/PipelineTable.tsx b/app/cdap/components/SourceControlManagement/LocalPipelineListView/PipelineTable.tsx index a72dd70ec37..49f7be87dc5 100644 --- a/app/cdap/components/SourceControlManagement/LocalPipelineListView/PipelineTable.tsx +++ b/app/cdap/components/SourceControlManagement/LocalPipelineListView/PipelineTable.tsx @@ -100,7 +100,7 @@ export const LocalPipelineTable = ({ return ( - +
diff --git a/app/cdap/components/SourceControlManagement/LocalPipelineListView/index.tsx b/app/cdap/components/SourceControlManagement/LocalPipelineListView/index.tsx index 1e0593b5aab..cad1ba3b9ad 100644 --- a/app/cdap/components/SourceControlManagement/LocalPipelineListView/index.tsx +++ b/app/cdap/components/SourceControlManagement/LocalPipelineListView/index.tsx @@ -20,6 +20,7 @@ import { useSelector } from 'react-redux'; import { getCurrentNamespace } from 'services/NamespaceStore'; import { countPushFailedPipelines, + dismissOperationAlert, fetchLatestOperation, getNamespacePipelineList, pushMultipleSelectedPipelines, @@ -59,7 +60,7 @@ export const LocalPipelineListView = () => { showFailedOnly, } = useSelector(({ push }) => push); - const { running: isAnOperationRunning, operation } = useSelector( + const { running: isAnOperationRunning, operation, showLastOperationInfo } = useSelector( ({ operationRun }) => operationRun ); @@ -145,6 +146,7 @@ export const LocalPipelineListView = () => { showFailedOnly={showFailedOnly} enableMultipleSelection={multiPushEnabled} disabled={isAnOperationRunning} + lastOperationInfoShown={showLastOperationInfo} /> { return ( + {operation && multiPushEnabled && showLastOperationInfo && ( + + )} - {operation && multiPushEnabled && } {selectedPipelines.length > 0 && (
diff --git a/app/cdap/components/SourceControlManagement/OperationAlert.tsx b/app/cdap/components/SourceControlManagement/OperationAlert.tsx index fe7581ce1d3..8e4bcbb255e 100644 --- a/app/cdap/components/SourceControlManagement/OperationAlert.tsx +++ b/app/cdap/components/SourceControlManagement/OperationAlert.tsx @@ -33,10 +33,12 @@ import { getCurrentNamespace } from 'services/NamespaceStore'; import { OperationStatus } from './OperationStatus'; import ExpandLess from '@material-ui/icons/ExpandLess'; import ExpandMore from '@material-ui/icons/ExpandMore'; +import CloseIcon from '@material-ui/icons/Close'; import { AlertErrorView } from './styles'; interface IOperationBannerProps { operation: IOperationRun; + onClose?(): void; } const StyledDiv = styled.div` @@ -45,12 +47,15 @@ const StyledDiv = styled.div` const ExpandWrapper = styled.div` height: 100%; - padding-top: 12px; + padding-top: 10px; + + display: flex; + justify-content: flex-end; `; const PREFIX = 'features.SourceControlManagement'; -export const OperationAlert = ({ operation }: IOperationBannerProps) => { +export const OperationAlert = ({ operation, onClose }: IOperationBannerProps) => { const [viewErrorExpanded, setViewErrorExpanded] = useState(false); const getOperationAction = () => { @@ -87,11 +92,22 @@ export const OperationAlert = ({ operation }: IOperationBannerProps) => { > {viewErrorExpanded ? : } + {onClose && ( + + )} ); } - return undefined; + return ( + onClose && ( + + ) + ); }; const renderOperationTime = () => { diff --git a/app/cdap/components/SourceControlManagement/RemotePipelineListView/RemotePipelineTable.tsx b/app/cdap/components/SourceControlManagement/RemotePipelineListView/RemotePipelineTable.tsx index dca38c86905..bed4a7d9870 100644 --- a/app/cdap/components/SourceControlManagement/RemotePipelineListView/RemotePipelineTable.tsx +++ b/app/cdap/components/SourceControlManagement/RemotePipelineListView/RemotePipelineTable.tsx @@ -31,6 +31,7 @@ interface IRepositoryPipelineTableProps { showFailedOnly: boolean; enableMultipleSelection?: boolean; disabled?: boolean; + lastOperationInfoShown?: boolean; } export const RemotePipelineTable = ({ @@ -39,6 +40,7 @@ export const RemotePipelineTable = ({ showFailedOnly, enableMultipleSelection = false, disabled = false, + lastOperationInfoShown = true, }: IRepositoryPipelineTableProps) => { const isSelected = (name: string) => selectedPipelines.indexOf(name) !== -1; @@ -91,8 +93,8 @@ export const RemotePipelineTable = ({ }; return ( - -
+ +
diff --git a/app/cdap/components/SourceControlManagement/RemotePipelineListView/index.tsx b/app/cdap/components/SourceControlManagement/RemotePipelineListView/index.tsx index bbeeadfbdda..401ca33c97d 100644 --- a/app/cdap/components/SourceControlManagement/RemotePipelineListView/index.tsx +++ b/app/cdap/components/SourceControlManagement/RemotePipelineListView/index.tsx @@ -34,6 +34,7 @@ import { toggleRemoteShowFailedOnly, pullAndDeployMultipleSelectedRemotePipelines, fetchLatestOperation, + dismissOperationAlert, } from '../store/ActionCreator'; import { LoadingAppLevel } from 'components/shared/LoadingAppLevel'; import { getCurrentNamespace } from 'services/NamespaceStore'; @@ -53,9 +54,13 @@ const PREFIX = 'features.SourceControlManagement.pull'; interface IRemotePipelineListViewProps { redirectOnSubmit?: boolean; + singlePipelineMode?: boolean; } -export const RemotePipelineListView = ({ redirectOnSubmit }: IRemotePipelineListViewProps) => { +export const RemotePipelineListView = ({ + redirectOnSubmit, + singlePipelineMode, +}: IRemotePipelineListViewProps) => { const { ready, remotePipelines, @@ -66,13 +71,13 @@ export const RemotePipelineListView = ({ redirectOnSubmit }: IRemotePipelineList pullViewErrorMsg, } = useSelector(({ pull }) => pull); - const { running: isAnOperationRunning, operation } = useSelector( + const { running: isAnOperationRunning, operation, showLastOperationInfo } = useSelector( ({ operationRun }) => operationRun ); - const multiPullEnabled = useFeatureFlagDefaultFalse( - 'source.control.management.multi.app.enabled' - ); + const multiPullEnabled = + useFeatureFlagDefaultFalse('source.control.management.multi.app.enabled') && + !singlePipelineMode; const pullFailedCount = countPullFailedPipelines(); useEffect(() => { @@ -158,6 +163,7 @@ export const RemotePipelineListView = ({ redirectOnSubmit }: IRemotePipelineList showFailedOnly={showFailedOnly} enableMultipleSelection={multiPullEnabled} disabled={isAnOperationRunning} + lastOperationInfoShown={showLastOperationInfo} /> setPullViewErrorMsg()} /> + {operation && multiPullEnabled && showLastOperationInfo && ( + + )} - {operation && multiPullEnabled && } {selectedPipelines.length > 0 && (
diff --git a/app/cdap/components/SourceControlManagement/SearchBox.tsx b/app/cdap/components/SourceControlManagement/SearchBox.tsx index cf252fa8099..54fd227a37e 100644 --- a/app/cdap/components/SourceControlManagement/SearchBox.tsx +++ b/app/cdap/components/SourceControlManagement/SearchBox.tsx @@ -32,7 +32,7 @@ const StyledTextField = styled(TextField)` `; const StyledDiv = styled.div` - margin: 12px 0px; + margin: 8px 0 4px 0px; `; interface ISearchBoxProps { diff --git a/app/cdap/components/SourceControlManagement/index.tsx b/app/cdap/components/SourceControlManagement/index.tsx index 6f4f5229408..9b47c990af6 100644 --- a/app/cdap/components/SourceControlManagement/index.tsx +++ b/app/cdap/components/SourceControlManagement/index.tsx @@ -24,11 +24,15 @@ import { useHistory } from 'react-router'; import { useOnUnmount } from 'services/react/customHooks/useOnUnmount'; import { reset, resetRemote } from './store/ActionCreator'; import ScmSyncTabs from './SyncTabs'; +import { useHideFooterInPage } from 'components/FooterContext'; +import { FeatureProvider } from 'services/react/providers/featureFlagProvider'; const PREFIX = 'features.SourceControlManagement'; const SourceControlManagementSyncView = () => { const history = useHistory(); + useHideFooterInPage(); + useOnUnmount(() => { resetRemote(); reset(); @@ -48,7 +52,9 @@ const SourceControlManagementSyncView = () => { history.push(closeAndBackLink); }} /> - + + + ); }; diff --git a/app/cdap/components/SourceControlManagement/store/ActionCreator.ts b/app/cdap/components/SourceControlManagement/store/ActionCreator.ts index e4250eac356..eed2b8772d3 100644 --- a/app/cdap/components/SourceControlManagement/store/ActionCreator.ts +++ b/app/cdap/components/SourceControlManagement/store/ActionCreator.ts @@ -439,3 +439,10 @@ export const refetchAllPipelines = () => { getNamespacePipelineList(getCurrentNamespace()); getRemotePipelineList(getCurrentNamespace()); }; + +export const dismissOperationAlert = () => { + SourceControlManagementSyncStore.dispatch({ + type: OperationRunActions.setShowLastOperationInfo, + payload: false, + }); +}; diff --git a/app/cdap/components/SourceControlManagement/styles.ts b/app/cdap/components/SourceControlManagement/styles.ts index a20e5289c79..6d6a3237ecb 100644 --- a/app/cdap/components/SourceControlManagement/styles.ts +++ b/app/cdap/components/SourceControlManagement/styles.ts @@ -22,8 +22,8 @@ export const TableBox = styled(TableContainer)` box-shadow: 0 1px 2px 0 rgb(0 0 0 / 20%); margin-top: 10px; margin-bottom: 30px; - max-height: calc(80vh - 200px); - min-height: calc(80vh - 300px); + max-height: calc(80vh - ${(props) => (props.lastOperationInfoShown ? '280px' : '200px')}); + min-height: calc(80vh - ${(props) => (props.lastOperationInfoShown ? '380px' : '200px')}); `; export const StyledTableCell = styled(TableCell)` diff --git a/app/cdap/main.js b/app/cdap/main.js index 758dc729b3b..c3ee02bb648 100644 --- a/app/cdap/main.js +++ b/app/cdap/main.js @@ -19,7 +19,7 @@ import 'react-hot-loader/patch'; import './globals'; import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; -import React, { Component } from 'react'; +import React, { Component, useEffect, useState } from 'react'; import { Route, Router, Switch } from 'react-router-dom'; import SessionTokenStore, { fetchSessionToken } from 'services/SessionTokenStore'; import { Theme, applyTheme } from 'services/ThemeHelper'; @@ -66,6 +66,7 @@ import { CookieBanner } from 'components/CookieBanner'; // See ./graphql/fragements/README.md import introspectionQueryResultData from '../../graphql/fragments/fragmentTypes.json'; import { TestidProvider } from './testids/TestidsProvider'; +import { FooterContext } from 'components/FooterContext'; require('../ui-utils/url-generator'); require('font-awesome-sass-loader!./styles/font-awesome.config.js'); @@ -397,7 +398,7 @@ class CDAP extends Component { ))} )} -
+ {this.props.showFooter &&
}
@@ -408,12 +409,36 @@ class CDAP extends Component { CDAP.propTypes = { children: PropTypes.node, + showFooter: PropTypes.bool, }; +CDAP.defaultProps = { + showFooter: true, +}; + +function CdapWithFooterContext() { + const [show, setShow] = useState(true); + + useEffect(() => { + const appContainer = document.getElementById('app-container'); + if (!show) { + appContainer.classList.add('no-footer'); + } else { + appContainer.classList.remove('no-footer'); + } + }, [show]); + + return ( + + + + ); +} + const RootComp = hot(() => { return ( - } /> + } /> ); }); diff --git a/app/cdap/styles/common.scss b/app/cdap/styles/common.scss index 8bf1f6dae50..049ef9d7f1d 100644 --- a/app/cdap/styles/common.scss +++ b/app/cdap/styles/common.scss @@ -60,6 +60,10 @@ body { margin-top: 48px; overflow-y: auto; height: calc(100vh - (#{$height-of-footer} + #{$height-of-header})); // Header + footer heights + + &.no-footer { + height: calc(100vh - #{$height-of-header}); + } } .container-fluid { padding-bottom: 52px; // footer height