diff --git a/ui/components/InfoModal.tsx b/ui/components/InfoModal.tsx index d7ce0f0e84..35b5a3e3a2 100644 --- a/ui/components/InfoModal.tsx +++ b/ui/components/InfoModal.tsx @@ -15,25 +15,33 @@ const ClusterName = styled(Text)` padding: ${(props) => props.theme.spacing.base}; `; +const OverflowWrapper = styled.div` + overflow-y: scroll; +`; + function InfoModal({ searchedNamespaces, onCloseModal, open }: Props) { const onClose = () => onCloseModal(false); const content = ( - - {Object.entries(searchedNamespaces || []).map( - ([kind, clusterNamespacesList]) => ( - -

kind: {kind}

- {clusterNamespacesList?.map((clusterNamespaces) => ( - - {clusterNamespaces.clusterName} - {clusterNamespaces.namespaces.join(", ")} - - ))} -
- ) - )} -
+ + + {Object.entries(searchedNamespaces || []).map( + ([kind, clusterNamespacesList]) => ( + +

kind: {kind}

+ {clusterNamespacesList?.map((clusterNamespaces) => ( + + + {clusterNamespaces.clusterName} + + {clusterNamespaces.namespaces.join(", ")} + + ))} +
+ ) + )} +
+
); return ( diff --git a/ui/components/Modal.tsx b/ui/components/Modal.tsx index 7238edf73d..8751fa74b8 100644 --- a/ui/components/Modal.tsx +++ b/ui/components/Modal.tsx @@ -1,15 +1,14 @@ import MaterialModal from "@material-ui/core/Modal"; import * as React from "react"; import styled from "styled-components"; -import Button from "./Button"; +import { IconButton } from "./Button"; import Flex from "./Flex"; +import Icon, { IconType } from "./Icon"; /** Modal Properties */ export interface Props { /** CSS MUI Overrides or other styling. (for the `
` that wraps Modal) */ className?: string; - /** CSS MUI Overrides or other styling. (for the Modal ``) */ - bodyClassName?: string; /** state variable to display Modal */ open: boolean; /** Close event handler function */ @@ -39,14 +38,9 @@ export const Body = styled.div` max-height: 90vh; `; -export const Content = styled.div` - overflow-y: scroll; -`; - /** Form Modal */ function UnstyledModal({ className, - bodyClassName, open, onClose, title, @@ -54,27 +48,31 @@ function UnstyledModal({ children, }: Props) { return ( -
- - - + + + +

{title}

-

{description}

+ + +
- {children} - - - - -
-
+ +

{description}

+ + {children} + + ); } diff --git a/ui/components/Sync/CheckboxActions.tsx b/ui/components/Sync/CheckboxActions.tsx index d3afdc9bb4..fde5fde289 100644 --- a/ui/components/Sync/CheckboxActions.tsx +++ b/ui/components/Sync/CheckboxActions.tsx @@ -6,6 +6,7 @@ import { useSyncFluxObject } from "../../hooks/automations"; import { useToggleSuspend } from "../../hooks/flux"; import { ObjectRef } from "../../lib/api/core/types.pb"; import { V2Routes } from "../../lib/types"; +import SuspendMessageModal from "./SuspendMessageModal"; import SyncControls, { SyncType } from "./SyncControls"; export const makeObjects = (checked: string[], rows: any[]): ObjectRef[] => { @@ -31,18 +32,23 @@ const noSource = { [V2Routes.ImageUpdates]: true, }; -function createSuspendHandler(reqObjects: ObjectRef[], suspend: boolean) { +function createSuspendHandler( + reqObjects: ObjectRef[], + suspend: boolean, + suspendMessage: string +) { const result = useToggleSuspend( { objects: reqObjects, suspend: suspend, + comment: suspendMessage, }, reqObjects[0]?.kind === "HelmRelease" || reqObjects[0]?.kind === "Kustomization" ? "automations" : "sources" ); - return () => result.mutateAsync(); + return result; } type Props = { @@ -53,6 +59,9 @@ type Props = { function CheckboxActions({ className, checked = [], rows = [] }: Props) { const [reqObjects, setReqObjects] = React.useState([]); + const [suspendMessageModalOpen, setSuspendMessageModalOpen] = + React.useState(false); + const [suspendMessage, setSuspendMessage] = React.useState(""); const location = useLocation(); React.useEffect(() => { @@ -70,18 +79,31 @@ function CheckboxActions({ className, checked = [], rows = [] }: Props) { const disableButtons = !reqObjects[0]; return ( - + <> + + setSuspendMessageModalOpen(!suspendMessageModalOpen) + } + onResumeClick={ + createSuspendHandler(reqObjects, false, suspendMessage).mutateAsync + } + /> + + ); } diff --git a/ui/components/Sync/SuspendMessageModal.tsx b/ui/components/Sync/SuspendMessageModal.tsx new file mode 100644 index 0000000000..7e0a21eb95 --- /dev/null +++ b/ui/components/Sync/SuspendMessageModal.tsx @@ -0,0 +1,80 @@ +import React, { Dispatch, SetStateAction } from "react"; +import { UseMutationResult } from "react-query/react"; +import styled from "styled-components"; +import { ToggleSuspendResourceResponse } from "../../lib/api/core/core.pb"; +import Button from "../Button"; +import Flex from "../Flex"; +import Modal from "../Modal"; + +export type Props = { + onCloseModal: Dispatch>; + open: boolean; + setSuspendMessage: Dispatch>; + suspend: UseMutationResult; + suspendMessage: string; + className?: string; +}; + +const MessageTextarea = styled.textarea` + width: 100%; + box-sizing: border-box; + font-family: inherit; + font-size: 100%; + border-radius: ${(props) => props.theme.spacing.xxs}; + resize: none; + margin-bottom: ${(props) => props.theme.spacing.base}; + padding: ${(props) => props.theme.spacing.xs}; + &:focus { + outline: ${(props) => props.theme.colors.primary} solid 2px; + } +`; + +function SuspendMessageModal({ + className, + onCloseModal, + open, + setSuspendMessage, + suspend, + suspendMessage, +}: Props) { + const closeHandler = () => { + setSuspendMessage(""); + onCloseModal(false); + }; + const suspendHandler = () => { + setSuspendMessage(suspendMessage); + suspend.mutateAsync({}); + setSuspendMessage(""); + onCloseModal(false); + }; + + const onClose = () => closeHandler(); + + const content = ( + <> + setSuspendMessage(ev.target.value)} + > + + + + + ); + + return ( + + ); +} + +export default SuspendMessageModal; diff --git a/ui/components/Sync/SyncActions.tsx b/ui/components/Sync/SyncActions.tsx index 674888cec6..9b48971bfa 100644 --- a/ui/components/Sync/SyncActions.tsx +++ b/ui/components/Sync/SyncActions.tsx @@ -3,6 +3,7 @@ import styled from "styled-components"; import { useSyncFluxObject } from "../../hooks/automations"; import { useToggleSuspend } from "../../hooks/flux"; import { Kind } from "../../lib/api/core/types.pb"; +import SuspendMessageModal from "./SuspendMessageModal"; import SyncControls, { SyncType } from "./SyncControls"; interface Props { @@ -38,7 +39,9 @@ const SyncActions = ({ const syncHandler = (syncType: SyncType) => { sync.mutateAsync({ withSource: syncType === SyncType.WithSource }); }; - + const [suspendMessageModalOpen, setSuspendMessageModalOpen] = + React.useState(false); + const [suspendMessage, setSuspendMessage] = React.useState(""); const objects = [ { name, @@ -52,6 +55,7 @@ const SyncActions = ({ { objects: objects, suspend: true, + comment: suspendMessage, }, "object" ); @@ -60,23 +64,35 @@ const SyncActions = ({ { objects: objects, suspend: false, + comment: "", }, "object" ); return ( - suspend.mutateAsync()} - onResumeClick={() => resume.mutateAsync()} - /> + <> + + setSuspendMessageModalOpen(!suspendMessageModalOpen) + } + onResumeClick={() => resume.mutateAsync()} + /> + + ); };