From 496ddb28e12464283cc69c79d91a86e5e2bddcf8 Mon Sep 17 00:00:00 2001 From: opudrovs Date: Tue, 31 Oct 2023 14:55:11 +0100 Subject: [PATCH] Replace the Sync/Suspend/Resume controls, used in the `SyncActions` and `CheckboxActions` components, with the new Sync/Suspend/Resume controls (the `SyncControl` component) (#4080) * Create the new `SyncControls` component for Sync/Suspend/Resume controls. * Move all components, related to syncing and suspending objects (existing `SyncActions` and `CheckboxActions` and new `SyncControls` and `ResumeIcon`), to the `Sync` folder. * Update the related UI snapshot. * Add `SyncControls` to exports. * Move custom actions to the start (left) of `SyncControls` buttons. * Re-arrange icons in `IconType` alphabetically. --- ui/components/AutomationDetail.tsx | 2 +- ui/components/CheckboxActions.tsx | 119 - ui/components/DataTable/DataTable.tsx | 2 +- ui/components/Icon.tsx | 309 +- .../ImageAutomationDetails.tsx | 4 +- ui/components/SourceDetail.tsx | 4 +- ui/components/Sync/CheckboxActions.tsx | 94 + ui/components/Sync/ResumeIcon.tsx | 16 + ui/components/Sync/SyncActions.tsx | 86 + ui/components/Sync/SyncControls.tsx | 233 ++ .../__tests__/CheckboxActions.test.tsx | 2 +- .../{ => Sync}/__tests__/SyncActions.test.tsx | 8 +- .../Sync/__tests__/SyncControls.test.tsx | 105 + .../__snapshots__/SyncActions.test.tsx.snap | 1530 ++++++++++ .../__snapshots__/SyncControls.test.tsx.snap | 2473 +++++++++++++++++ ui/components/SyncActions.tsx | 79 - ui/components/SyncButton.tsx | 109 - .../__snapshots__/SyncActions.test.tsx.snap | 803 ------ ui/index.ts | 4 +- ui/lib/theme.ts | 28 + 20 files changed, 4741 insertions(+), 1269 deletions(-) delete mode 100644 ui/components/CheckboxActions.tsx create mode 100644 ui/components/Sync/CheckboxActions.tsx create mode 100644 ui/components/Sync/ResumeIcon.tsx create mode 100644 ui/components/Sync/SyncActions.tsx create mode 100644 ui/components/Sync/SyncControls.tsx rename ui/components/{ => Sync}/__tests__/CheckboxActions.test.tsx (93%) rename ui/components/{ => Sync}/__tests__/SyncActions.test.tsx (88%) create mode 100644 ui/components/Sync/__tests__/SyncControls.test.tsx create mode 100644 ui/components/Sync/__tests__/__snapshots__/SyncActions.test.tsx.snap create mode 100644 ui/components/Sync/__tests__/__snapshots__/SyncControls.test.tsx.snap delete mode 100644 ui/components/SyncActions.tsx delete mode 100644 ui/components/SyncButton.tsx delete mode 100644 ui/components/__tests__/__snapshots__/SyncActions.test.tsx.snap diff --git a/ui/components/AutomationDetail.tsx b/ui/components/AutomationDetail.tsx index f1f9b48cbd7..33f5503e444 100644 --- a/ui/components/AutomationDetail.tsx +++ b/ui/components/AutomationDetail.tsx @@ -21,7 +21,7 @@ import ReconciledObjectsTable from "./ReconciledObjectsTable"; import ReconciliationGraph from "./ReconciliationGraph"; import RequestStateHandler from "./RequestStateHandler"; import SubRouterTabs, { RouterTab } from "./SubRouterTabs"; -import SyncActions from "./SyncActions"; +import SyncActions from "./Sync/SyncActions"; import Text from "./Text"; import Timestamp from "./Timestamp"; import YamlView from "./YamlView"; diff --git a/ui/components/CheckboxActions.tsx b/ui/components/CheckboxActions.tsx deleted file mode 100644 index 55daf535984..00000000000 --- a/ui/components/CheckboxActions.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { Tooltip } from "@material-ui/core"; -import _ from "lodash"; -import * as React from "react"; -import { useLocation } from "react-router-dom"; -import styled from "styled-components"; -import { useSyncFluxObject } from "../hooks/automations"; -import { useToggleSuspend } from "../hooks/flux"; -import { ObjectRef } from "../lib/api/core/types.pb"; -import { V2Routes } from "../lib/types"; -import Button from "./Button"; -import Flex from "./Flex"; -import Icon, { IconType } from "./Icon"; -import SyncButton from "./SyncButton"; - -export const makeObjects = (checked: string[], rows: any[]): ObjectRef[] => { - const objects = []; - checked.forEach((uid) => { - const row = _.find(rows, (row) => { - return uid === row.uid; - }); - if (row) - return objects.push({ - kind: row.type, - name: row.name, - namespace: row.namespace, - clusterName: row.clusterName, - }); - }); - return objects; -}; - -const DefaultSync: React.FC<{ reqObjects: ObjectRef[] }> = ({ reqObjects }) => { - const defaultSync = useSyncFluxObject(reqObjects); - const location = useLocation(); - const noSource = { - [V2Routes.Sources]: true, - [V2Routes.ImageRepositories]: true, - [V2Routes.ImageUpdates]: true, - }; - return ( - defaultSync.mutateAsync(opts)} - hideDropdown={noSource[location.pathname]} - /> - ); -}; - -const DefaultSuspend: React.FC<{ - reqObjects: ObjectRef[]; - suspend: boolean; -}> = ({ reqObjects, suspend }) => { - function createDefaultSuspendHandler( - reqObjects: ObjectRef[], - suspend: boolean - ) { - const result = useToggleSuspend( - { - objects: reqObjects, - suspend: suspend, - }, - reqObjects[0]?.kind === "HelmRelease" || - reqObjects[0]?.kind === "Kustomization" - ? "automations" - : "sources" - ); - return () => result.mutateAsync(); - } - - return ( - -
- -
-
- ); -}; - -type Props = { - className?: string; - checked?: string[]; - rows?: any[]; -}; - -function CheckboxActions({ className, checked = [], rows = [] }: Props) { - const [reqObjects, setReqObjects] = React.useState([]); - - React.useEffect(() => { - if (checked.length > 0 && rows.length) - setReqObjects(makeObjects(checked, rows)); - else setReqObjects([]); - }, [checked, rows]); - - return ( - - - - - - ); -} - -export default styled(CheckboxActions).attrs({ - className: CheckboxActions.name, -})` - margin-right: 8px; -`; diff --git a/ui/components/DataTable/DataTable.tsx b/ui/components/DataTable/DataTable.tsx index 1a676cec589..bd4aa9ef64c 100644 --- a/ui/components/DataTable/DataTable.tsx +++ b/ui/components/DataTable/DataTable.tsx @@ -6,7 +6,6 @@ import styled from "styled-components"; import { ThemeTypes } from "../../contexts/AppContext"; import { SearchedNamespaces } from "../../lib/types"; import { IconButton } from "../Button"; -import CheckboxActions from "../CheckboxActions"; import ChipGroup from "../ChipGroup"; import FilterDialog, { FilterConfig, @@ -16,6 +15,7 @@ import FilterDialog, { import Flex from "../Flex"; import Icon, { IconType } from "../Icon"; import SearchField from "../SearchField"; +import CheckboxActions from "../Sync/CheckboxActions"; import { filterRows, filterSelectionsToQueryString, diff --git a/ui/components/Icon.tsx b/ui/components/Icon.tsx index c25c592fee6..f41a0ccd83e 100644 --- a/ui/components/Icon.tsx +++ b/ui/components/Icon.tsx @@ -29,8 +29,10 @@ import Remove from "@material-ui/icons/Remove"; import RemoveCircleIcon from "@material-ui/icons/RemoveCircle"; import SaveAltIcon from "@material-ui/icons/SaveAlt"; import SearchIcon from "@material-ui/icons/Search"; +import SettingsIcon from "@material-ui/icons/Settings"; import SkipNextIcon from "@material-ui/icons/SkipNext"; import SkipPreviousIcon from "@material-ui/icons/SkipPrevious"; +import SyncIcon from "@material-ui/icons/Sync"; import VerifiedUser from "@material-ui/icons/VerifiedUser"; import WarningIcon from "@material-ui/icons/Warning"; import * as React from "react"; @@ -57,69 +59,73 @@ import SourcesIcon from "./NavIcons/SourcesIcon"; import TemplatesIcon from "./NavIcons/TemplatesIcon"; import TerraformIcon from "./NavIcons/TerraformIcon"; import WorkspacesIcon from "./NavIcons/WorkspacesIcon"; +import ResumeIcon from "./Sync/ResumeIcon"; import Text from "./Text"; export enum IconType { - CheckMark, Account, - ExternalTab, AddIcon, - ArrowUpwardIcon, - ArrowDropDownIcon, + ApplicationsIcon, ArrowDownwardRoundedIcon, + ArrowDropDownIcon, + ArrowUpwardIcon, ArrowUpwardRoundedIcon, - KeyboardArrowRightIcon, - KeyboardArrowDownIcon, - DeleteIcon, - SaveAltIcon, - ErrorIcon, + CallMade, + CallReceived, CheckCircleIcon, - HourglassFullIcon, - NavigateNextIcon, - NavigateBeforeIcon, - SkipNextIcon, - SkipPreviousIcon, - RemoveCircleIcon, - FilterIcon, + CheckMark, ClearIcon, - SearchIcon, - LogoutIcon, - SuccessIcon, + ClustersIcon, + DeleteIcon, + DeliveryIcon, + DocsIcon, + EditIcon, + ErrorIcon, + ExploreIcon, + ExternalTab, FailedIcon, - SuspendedIcon, FileCopyIcon, - ReconcileIcon, + FilterIcon, + FindInPage, FluxIcon, FluxIconHover, - DocsIcon, - ApplicationsIcon, - PlayIcon, - PauseIcon, - NotificationsIcon, - SourcesIcon, - ImageAutomationIcon, - DeliveryIcon, GitOpsRunIcon, - PipelinesIcon, - TerraformIcon, GitOpsSetsIcon, + HourglassFullIcon, + ImageAutomationIcon, + InfoIcon, + KeyboardArrowDownIcon, + KeyboardArrowRightIcon, + LogoutIcon, + NavigateBeforeIcon, + NavigateNextIcon, + NotificationsIcon, + PauseIcon, + PendingActionIcon, + PipelinesIcon, + PlayIcon, PoliciesIcon, + Policy, PolicyConfigsIcon, - WorkspacesIcon, + ReconcileIcon, + Remove, + RemoveCircleIcon, + ResumeIcon, + SaveAltIcon, + SearchIcon, SecretsIcon, + SettingsIcon, + SkipNextIcon, + SkipPreviousIcon, + SourcesIcon, + SuccessIcon, + SuspendedIcon, + SyncIcon, TemplatesIcon, - ClustersIcon, - ExploreIcon, - PendingActionIcon, - InfoIcon, - CallReceived, - CallMade, - Remove, - EditIcon, + TerraformIcon, VerifiedUser, - Policy, - FindInPage, WarningIcon, + WorkspacesIcon, } type Props = { @@ -133,181 +139,192 @@ type Props = { function getIcon(i: IconType) { switch (i) { - case IconType.CheckMark: - return CheckCircleIcon; - case IconType.Account: return PersonIcon; - case IconType.ExternalTab: - return LaunchIcon; - case IconType.AddIcon: return AddIcon; + case IconType.ApplicationsIcon: + return ApplicationsIcon; + + case IconType.ArrowDownwardRoundedIcon: + return ArrowDownwardRoundedIcon; + + case IconType.ArrowDropDownIcon: + return ArrowDropDownIcon; + case IconType.ArrowUpwardIcon: return ArrowUpwardIcon; - case IconType.KeyboardArrowRightIcon: - return KeyboardArrowRightIcon; - case IconType.KeyboardArrowDownIcon: - return KeyboardArrowDownIcon; - case IconType.DeleteIcon: - return DeleteIcon; + case IconType.ArrowUpwardRoundedIcon: + return ArrowUpwardRoundedIcon; - case IconType.SaveAltIcon: - return SaveAltIcon; + case IconType.CallMade: + return CallMade; + + case IconType.CallReceived: + return CallReceived; case IconType.CheckCircleIcon: return CheckCircleIcon; - case IconType.HourglassFullIcon: - return HourglassFullIcon; + case IconType.CheckMark: + return CheckCircleIcon; + + case IconType.ClearIcon: + return ClearIcon; + + case IconType.ClustersIcon: + return ClustersIcon; + + case IconType.DeleteIcon: + return DeleteIcon; + + case IconType.DeliveryIcon: + return DeliveryIcon; + + case IconType.DocsIcon: + return DocsIcon; + + case IconType.EditIcon: + return EditIcon; case IconType.ErrorIcon: return ErrorIcon; - case IconType.NavigateNextIcon: - return NavigateNextIcon; - - case IconType.NavigateBeforeIcon: - return NavigateBeforeIcon; + case IconType.ExploreIcon: + return ExploreIcon; - case IconType.SkipNextIcon: - return SkipNextIcon; + case IconType.ExternalTab: + return LaunchIcon; - case IconType.SkipPreviousIcon: - return SkipPreviousIcon; + case IconType.FailedIcon: + return ErrorIcon; - case IconType.RemoveCircleIcon: - return RemoveCircleIcon; + case IconType.FileCopyIcon: + return FileCopyIcon; case IconType.FilterIcon: return FilterIcon; - case IconType.ClearIcon: - return ClearIcon; + case IconType.FindInPage: + return FindInPage; - case IconType.SearchIcon: - return SearchIcon; + case IconType.FluxIcon: + return FluxIcon; - case IconType.LogoutIcon: - return LogoutIcon; + case IconType.GitOpsRunIcon: + return GitOpsRunIcon; - case IconType.SuccessIcon: - return () => ; + case IconType.GitOpsSetsIcon: + return GitOpsSetsIcon; - case IconType.FailedIcon: - return ErrorIcon; + case IconType.HourglassFullIcon: + return HourglassFullIcon; - case IconType.SuspendedIcon: - return () => ; + case IconType.ImageAutomationIcon: + return ImageAutomationIcon; - case IconType.ReconcileIcon: - return () => ; + case IconType.InfoIcon: + return InfoIcon; - case IconType.PendingActionIcon: - return () => ; + case IconType.KeyboardArrowDownIcon: + return KeyboardArrowDownIcon; - case IconType.ArrowDropDownIcon: - return ArrowDropDownIcon; + case IconType.KeyboardArrowRightIcon: + return KeyboardArrowRightIcon; - case IconType.ArrowDownwardRoundedIcon: - return ArrowDownwardRoundedIcon; + case IconType.LogoutIcon: + return LogoutIcon; - case IconType.ArrowUpwardRoundedIcon: - return ArrowUpwardRoundedIcon; + case IconType.NavigateBeforeIcon: + return NavigateBeforeIcon; - case IconType.FileCopyIcon: - return FileCopyIcon; + case IconType.NavigateNextIcon: + return NavigateNextIcon; - case IconType.PlayIcon: - return PlayIcon; + case IconType.NotificationsIcon: + return NotificationsIcon; case IconType.PauseIcon: return PauseIcon; - case IconType.SourcesIcon: - return SourcesIcon; - - case IconType.ImageAutomationIcon: - return ImageAutomationIcon; - - case IconType.DeliveryIcon: - return DeliveryIcon; - - case IconType.GitOpsRunIcon: - return GitOpsRunIcon; + case IconType.PendingActionIcon: + return () => ; case IconType.PipelinesIcon: return PipelinesIcon; - case IconType.TerraformIcon: - return TerraformIcon; + case IconType.PlayIcon: + return PlayIcon; - case IconType.ApplicationsIcon: - return ApplicationsIcon; + case IconType.PoliciesIcon: + return PoliciesIcon; - case IconType.DocsIcon: - return DocsIcon; + case IconType.Policy: + return Policy; - case IconType.FluxIcon: - return FluxIcon; + case IconType.PolicyConfigsIcon: + return PolicyConfigsIcon; - case IconType.GitOpsSetsIcon: - return GitOpsSetsIcon; + case IconType.ReconcileIcon: + return () => ; - case IconType.NotificationsIcon: - return NotificationsIcon; + case IconType.Remove: + return Remove; - case IconType.PoliciesIcon: - return PoliciesIcon; + case IconType.RemoveCircleIcon: + return RemoveCircleIcon; - case IconType.PolicyConfigsIcon: - return PolicyConfigsIcon; + case IconType.ResumeIcon: + return ResumeIcon; - case IconType.VerifiedUser: - return VerifiedUser; + case IconType.SaveAltIcon: + return SaveAltIcon; - case IconType.Policy: - return Policy; + case IconType.SearchIcon: + return SearchIcon; case IconType.SecretsIcon: return SecretsIcon; - case IconType.TemplatesIcon: - return TemplatesIcon; + case IconType.SettingsIcon: + return SettingsIcon; - case IconType.WorkspacesIcon: - return WorkspacesIcon; + case IconType.SkipNextIcon: + return SkipNextIcon; - case IconType.ClustersIcon: - return ClustersIcon; + case IconType.SkipPreviousIcon: + return SkipPreviousIcon; - case IconType.ExploreIcon: - return ExploreIcon; + case IconType.SourcesIcon: + return SourcesIcon; - case IconType.InfoIcon: - return InfoIcon; + case IconType.SuccessIcon: + return () => ; - case IconType.CallReceived: - return CallReceived; + case IconType.SuspendedIcon: + return () => ; - case IconType.CallMade: - return CallMade; + case IconType.SyncIcon: + return SyncIcon; - case IconType.Remove: - return Remove; + case IconType.TemplatesIcon: + return TemplatesIcon; - case IconType.EditIcon: - return EditIcon; + case IconType.TerraformIcon: + return TerraformIcon; - case IconType.FindInPage: - return FindInPage; + case IconType.VerifiedUser: + return VerifiedUser; case IconType.WarningIcon: return WarningIcon; + case IconType.WorkspacesIcon: + return WorkspacesIcon; + default: break; } diff --git a/ui/components/ImageAutomation/ImageAutomationDetails.tsx b/ui/components/ImageAutomation/ImageAutomationDetails.tsx index fada8cbacc1..96c2b4f0a14 100644 --- a/ui/components/ImageAutomation/ImageAutomationDetails.tsx +++ b/ui/components/ImageAutomation/ImageAutomationDetails.tsx @@ -7,7 +7,7 @@ import Flex from "../Flex"; import PageStatus from "../PageStatus"; import HeaderRows, { RowItem } from "../Policies/Utils/HeaderRows"; import SubRouterTabs, { RouterTab } from "../SubRouterTabs"; -import SyncActions from "../SyncActions"; +import SyncActions from "../Sync/SyncActions"; import YamlView from "../YamlView"; interface Props { className?: string; @@ -38,7 +38,7 @@ const ImageAutomationDetails = ({ clusterName={clusterName} kind={kind} suspended={suspended} - hideDropdown + hideSyncOptions /> )} diff --git a/ui/components/SourceDetail.tsx b/ui/components/SourceDetail.tsx index 605976f51f5..ea278870449 100644 --- a/ui/components/SourceDetail.tsx +++ b/ui/components/SourceDetail.tsx @@ -14,7 +14,7 @@ import LoadingPage from "./LoadingPage"; import Metadata from "./Metadata"; import PageStatus from "./PageStatus"; import SubRouterTabs, { RouterTab } from "./SubRouterTabs"; -import SyncActions from "./SyncActions"; +import SyncActions from "./Sync/SyncActions"; import YamlView from "./YamlView"; //must specify OCIRepository type, artifactMetadata causes errors on the Source type @@ -86,7 +86,7 @@ function SourceDetail({ className, source, info, type, customActions }: Props) { clusterName={clusterName} kind={type} suspended={suspended} - hideDropdown + hideSyncOptions customActions={customActions} /> diff --git a/ui/components/Sync/CheckboxActions.tsx b/ui/components/Sync/CheckboxActions.tsx new file mode 100644 index 00000000000..d3afdc9bb46 --- /dev/null +++ b/ui/components/Sync/CheckboxActions.tsx @@ -0,0 +1,94 @@ +import _ from "lodash"; +import * as React from "react"; +import { useLocation } from "react-router-dom"; +import styled from "styled-components"; +import { useSyncFluxObject } from "../../hooks/automations"; +import { useToggleSuspend } from "../../hooks/flux"; +import { ObjectRef } from "../../lib/api/core/types.pb"; +import { V2Routes } from "../../lib/types"; +import SyncControls, { SyncType } from "./SyncControls"; + +export const makeObjects = (checked: string[], rows: any[]): ObjectRef[] => { + const objects = []; + checked.forEach((uid) => { + const row = _.find(rows, (row) => { + return uid === row.uid; + }); + if (row) + return objects.push({ + kind: row.type, + name: row.name, + namespace: row.namespace, + clusterName: row.clusterName, + }); + }); + return objects; +}; + +const noSource = { + [V2Routes.Sources]: true, + [V2Routes.ImageRepositories]: true, + [V2Routes.ImageUpdates]: true, +}; + +function createSuspendHandler(reqObjects: ObjectRef[], suspend: boolean) { + const result = useToggleSuspend( + { + objects: reqObjects, + suspend: suspend, + }, + reqObjects[0]?.kind === "HelmRelease" || + reqObjects[0]?.kind === "Kustomization" + ? "automations" + : "sources" + ); + return () => result.mutateAsync(); +} + +type Props = { + className?: string; + checked?: string[]; + rows?: any[]; +}; + +function CheckboxActions({ className, checked = [], rows = [] }: Props) { + const [reqObjects, setReqObjects] = React.useState([]); + const location = useLocation(); + + React.useEffect(() => { + if (checked.length > 0 && rows.length) + setReqObjects(makeObjects(checked, rows)); + else setReqObjects([]); + }, [checked, rows]); + + const sync = useSyncFluxObject(reqObjects); + + const syncHandler = (syncType: SyncType) => { + sync.mutateAsync({ withSource: syncType === SyncType.WithSource }); + }; + + const disableButtons = !reqObjects[0]; + + return ( + + ); +} + +export default styled(CheckboxActions).attrs({ + className: CheckboxActions.name, +})` + width: 50%; + min-width: fit-content; + margin-right: 8px; +`; diff --git a/ui/components/Sync/ResumeIcon.tsx b/ui/components/Sync/ResumeIcon.tsx new file mode 100644 index 00000000000..8934b591458 --- /dev/null +++ b/ui/components/Sync/ResumeIcon.tsx @@ -0,0 +1,16 @@ +import * as React from "react"; + +function ResumeIcon() { + return ( + + + + ); +} + +export default ResumeIcon; diff --git a/ui/components/Sync/SyncActions.tsx b/ui/components/Sync/SyncActions.tsx new file mode 100644 index 00000000000..674888cec62 --- /dev/null +++ b/ui/components/Sync/SyncActions.tsx @@ -0,0 +1,86 @@ +import React from "react"; +import styled from "styled-components"; +import { useSyncFluxObject } from "../../hooks/automations"; +import { useToggleSuspend } from "../../hooks/flux"; +import { Kind } from "../../lib/api/core/types.pb"; +import SyncControls, { SyncType } from "./SyncControls"; + +interface Props { + name?: string; + namespace?: string; + clusterName?: string; + kind?: Kind; + suspended?: boolean; + hideSyncOptions?: boolean; + customActions?: JSX.Element[]; + className?: string; +} + +const SyncActions = ({ + name, + namespace, + clusterName, + kind, + suspended, + hideSyncOptions, + customActions, + className, +}: Props) => { + const sync = useSyncFluxObject([ + { + name, + namespace, + clusterName, + kind: kind, + }, + ]); + + const syncHandler = (syncType: SyncType) => { + sync.mutateAsync({ withSource: syncType === SyncType.WithSource }); + }; + + const objects = [ + { + name, + namespace, + clusterName, + kind: kind, + }, + ]; + + const suspend = useToggleSuspend( + { + objects: objects, + suspend: true, + }, + "object" + ); + + const resume = useToggleSuspend( + { + objects: objects, + suspend: false, + }, + "object" + ); + + return ( + suspend.mutateAsync()} + onResumeClick={() => resume.mutateAsync()} + /> + ); +}; + +export default styled(SyncActions)` + width: 50%; + min-width: fit-content; +`; diff --git a/ui/components/Sync/SyncControls.tsx b/ui/components/Sync/SyncControls.tsx new file mode 100644 index 00000000000..26061053b2a --- /dev/null +++ b/ui/components/Sync/SyncControls.tsx @@ -0,0 +1,233 @@ +import { + FormControl, + FormControlLabel, + Radio, + RadioGroup, + Tooltip, +} from "@material-ui/core"; +import { alpha } from "@material-ui/core/styles/colorManipulator"; +import React from "react"; +import styled, { keyframes } from "styled-components"; +import { ThemeTypes } from "../../contexts/AppContext"; +import Button from "../Button"; +import CustomActions from "../CustomActions"; +import Flex from "../Flex"; +import Icon, { IconType } from "../Icon"; +import Spacer from "../Spacer"; + +interface Props { + className?: string; + syncLoading?: boolean; + syncDisabled?: boolean; + suspendDisabled?: boolean; + resumeDisabled?: boolean; + hideSyncOptions?: boolean; + hideSuspend?: boolean; + tooltipSuffix?: string; + customActions?: JSX.Element[]; + onSyncClick: (syncType: SyncType) => void; + onSuspendClick?: () => void; + onResumeClick?: () => void; +} + +export enum SyncType { + WithSource = "WithSource", + WithoutSource = "WithoutSource", +} + +const rotateAnimation = keyframes` + 0% { transform: rotate(0deg); } + 100% { transform: rotate(-360deg); } +`; + +const SourceLabel = styled(FormControlLabel)` + &.MuiFormControlLabel-root { + margin-right: 0; + margin-left: 0; + } + + .MuiFormControlLabel-label { + color: ${(props) => + props.theme.mode === ThemeTypes.Dark + ? props.theme.colors.neutral30 + : props.theme.colors.neutral40}; + + &.Mui-disabled { + color: ${(props) => + props.theme.mode === ThemeTypes.Dark + ? props.theme.colors.primary30 + : props.theme.colors.neutral20}; + } + } + + .MuiTypography-root { + margin-left: ${(props) => props.theme.spacing.xs}; + } +`; + +export const IconButton = styled(Button)` + &.MuiButton-root { + border-radius: 50%; + min-width: 32px; + height: 32px; + padding: 0; + + :disabled { + svg { + fill: ${(props) => + props.theme.mode === ThemeTypes.Dark + ? props.theme.colors.primary30 + : props.theme.colors.neutral20}; + } + } + + :hover { + background-color: ${(props) => + props.theme.mode === ThemeTypes.Dark + ? alpha(props.theme.colors.primary10, 0.2) + : alpha(props.theme.colors.primary, 0.1)}; + } + } + &.MuiButton-text { + padding: 0; + } +`; + +const SyncControls = ({ + className, + syncLoading, + syncDisabled, + suspendDisabled, + resumeDisabled, + hideSyncOptions, + hideSuspend, + tooltipSuffix = "", + customActions, + onSyncClick, + onSuspendClick, + onResumeClick, +}: Props) => { + const [syncType, setSyncType] = React.useState( + hideSyncOptions ? SyncType.WithoutSource : SyncType.WithSource + ); + + const handleSyncTypeChange = (value: SyncType) => { + setSyncType(value); + }; + + const disableSyncButtons = syncDisabled || syncLoading; + + return ( + + {customActions && ( + <> + + + + )} + + + {!hideSyncOptions && ( + <> + + { + handleSyncTypeChange(event.target.value as SyncType); + }} + > + } + label="with Source" + disabled={disableSyncButtons} + /> + + } + label="without Source" + disabled={disableSyncButtons} + /> + + + + + )} + +
+ onSyncClick(syncType)} + > + + +
+
+ {!hideSuspend && ( + <> + + +
+ + + +
+
+ + +
+ + + +
+
+ + )} +
+ ); +}; + +export default styled(SyncControls)` + .sync-icon-button { + text-transform: uppercase; + pointer-events: none; + } + + .rotate-icon { + color: ${(props) => props.theme.colors.primary10}; + + animation: 1s linear infinite ${rotateAnimation}; + } +`; diff --git a/ui/components/__tests__/CheckboxActions.test.tsx b/ui/components/Sync/__tests__/CheckboxActions.test.tsx similarity index 93% rename from ui/components/__tests__/CheckboxActions.test.tsx rename to ui/components/Sync/__tests__/CheckboxActions.test.tsx index d576c377cc0..0d0acdba02c 100644 --- a/ui/components/__tests__/CheckboxActions.test.tsx +++ b/ui/components/Sync/__tests__/CheckboxActions.test.tsx @@ -1,5 +1,5 @@ import "jest-styled-components"; -import { Kind } from "../../lib/api/core/types.pb"; +import { Kind } from "../../../lib/api/core/types.pb"; import { makeObjects } from "../CheckboxActions"; describe("CheckboxActions", () => { diff --git a/ui/components/__tests__/SyncActions.test.tsx b/ui/components/Sync/__tests__/SyncActions.test.tsx similarity index 88% rename from ui/components/__tests__/SyncActions.test.tsx rename to ui/components/Sync/__tests__/SyncActions.test.tsx index fd790e8c7dd..a6fc56bf5ae 100644 --- a/ui/components/__tests__/SyncActions.test.tsx +++ b/ui/components/Sync/__tests__/SyncActions.test.tsx @@ -1,12 +1,12 @@ import "jest-styled-components"; import React from "react"; import renderer from "react-test-renderer"; -import { CoreClientContext } from "../../contexts/CoreClientContext"; +import { CoreClientContext } from "../../../contexts/CoreClientContext"; import { createCoreMockClient, withContext, withTheme, -} from "../../lib/test-utils"; +} from "../../../lib/test-utils"; import SyncActions from "../SyncActions"; describe("SyncActions", () => { @@ -45,13 +45,13 @@ describe("SyncActions", () => { .toJSON(); expect(tree).toMatchSnapshot(); }); - it("hideDropdown", () => { + it("hideSyncOptions", () => { const tree = renderer .create( withTheme( withContext( - + , "/", {} diff --git a/ui/components/Sync/__tests__/SyncControls.test.tsx b/ui/components/Sync/__tests__/SyncControls.test.tsx new file mode 100644 index 00000000000..e3a4f6498c7 --- /dev/null +++ b/ui/components/Sync/__tests__/SyncControls.test.tsx @@ -0,0 +1,105 @@ +import "jest-styled-components"; +import React from "react"; +import renderer from "react-test-renderer"; +import { CoreClientContext } from "../../../contexts/CoreClientContext"; +import { + createCoreMockClient, + withContext, + withTheme, +} from "../../../lib/test-utils"; +import SyncControls from "../SyncControls"; + +describe("SyncControls", () => { + describe("snapshots", () => { + const mockContext = { api: createCoreMockClient({}), featureFlags: {} }; + + it("non-suspended", () => { + const tree = renderer + .create( + withTheme( + withContext( + + {}} /> + , + "/", + {} + ) + ) + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); + it("allButtonsDisabled", () => { + const tree = renderer + .create( + withTheme( + withContext( + + {}} + /> + , + "/", + {} + ) + ) + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); + it("hideSyncOptions", () => { + const tree = renderer + .create( + withTheme( + withContext( + + {}} /> + , + "/", + {} + ) + ) + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); + it("hideSuspend", () => { + const tree = renderer + .create( + withTheme( + withContext( + + {}} /> + , + "/", + {} + ) + ) + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); + it("hasTooltipSuffix", () => { + const tree = renderer + .create( + withTheme( + withContext( + + {}} + /> + , + "/", + {} + ) + ) + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); + }); +}); diff --git a/ui/components/Sync/__tests__/__snapshots__/SyncActions.test.tsx.snap b/ui/components/Sync/__tests__/__snapshots__/SyncActions.test.tsx.snap new file mode 100644 index 00000000000..1266319ecd2 --- /dev/null +++ b/ui/components/Sync/__tests__/__snapshots__/SyncActions.test.tsx.snap @@ -0,0 +1,1530 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SyncActions snapshots hideSyncOptions 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c5 svg { + height: 24px; + width: 24px; +} + +.c5 svg path.path-fill, +.c5 svg line.path-fill, +.c5 svg polygon.path-fill, +.c5 svg rect.path-fill, +.c5 svg circle.path-fill, +.c5 svg polyline.path-fill { + fill: !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c5 svg path.stroke-fill, +.c5 svg line.stroke-fill, +.c5 svg polygon.stroke-fill, +.c5 svg rect.stroke-fill, +.c5 svg circle.stroke-fill, +.c5 svg polyline.stroke-fill { + stroke: !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c5 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c5.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c5.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c5 img { + width: 24px; +} + +.c8 svg { + fill: #009CCC; + height: 24px; + width: 24px; +} + +.c8 svg path.path-fill, +.c8 svg line.path-fill, +.c8 svg polygon.path-fill, +.c8 svg rect.path-fill, +.c8 svg circle.path-fill, +.c8 svg polyline.path-fill { + fill: #009CCC !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c8 svg path.stroke-fill, +.c8 svg line.stroke-fill, +.c8 svg polygon.stroke-fill, +.c8 svg rect.stroke-fill, +.c8 svg circle.stroke-fill, +.c8 svg polyline.stroke-fill { + stroke: #009CCC !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c8 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c8.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c8.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c8 img { + width: 24px; +} + +.c6 { + padding: 4px; +} + +.c3.MuiButton-root { + height: 32px; + font-size: 12px; + -webkit-letter-spacing: 1px; + -moz-letter-spacing: 1px; + -ms-letter-spacing: 1px; + letter-spacing: 1px; + line-height: 1; + border-radius: 2px; + font-weight: 600; +} + +.c3.MuiButton-outlined { + padding: 8px 12px; +} + +.c7.MuiButton-root { + border-radius: 50%; + min-width: 32px; + height: 32px; + padding: 0; +} + +.c7.MuiButton-root:disabled svg { + fill: #d8d8d8; +} + +.c7.MuiButton-root:hover { + background-color: rgba(0,179,236,0.1); +} + +.c7.MuiButton-text { + padding: 0; +} + +.c1 .sync-icon-button { + text-transform: uppercase; + pointer-events: none; +} + +.c1 .rotate-icon { + color: #009CCC; + -webkit-animation: 1s linear infinite dxlcOg; + animation: 1s linear infinite dxlcOg; +} + +.c2 { + width: 50%; + min-width: -webkit-fit-content; + min-width: -moz-fit-content; + min-width: fit-content; +} + +
+ +
+
+ +
+
+
+ +
+
+
+ +
+
+`; + +exports[`SyncActions snapshots non-suspended 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c5 svg { + height: 24px; + width: 24px; +} + +.c5 svg path.path-fill, +.c5 svg line.path-fill, +.c5 svg polygon.path-fill, +.c5 svg rect.path-fill, +.c5 svg circle.path-fill, +.c5 svg polyline.path-fill { + fill: !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c5 svg path.stroke-fill, +.c5 svg line.stroke-fill, +.c5 svg polygon.stroke-fill, +.c5 svg rect.stroke-fill, +.c5 svg circle.stroke-fill, +.c5 svg polyline.stroke-fill { + stroke: !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c5 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c5.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c5.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c5 img { + width: 24px; +} + +.c9 svg { + fill: #009CCC; + height: 24px; + width: 24px; +} + +.c9 svg path.path-fill, +.c9 svg line.path-fill, +.c9 svg polygon.path-fill, +.c9 svg rect.path-fill, +.c9 svg circle.path-fill, +.c9 svg polyline.path-fill { + fill: #009CCC !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c9 svg path.stroke-fill, +.c9 svg line.stroke-fill, +.c9 svg polygon.stroke-fill, +.c9 svg rect.stroke-fill, +.c9 svg circle.stroke-fill, +.c9 svg polyline.stroke-fill { + stroke: #009CCC !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c9 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c9.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c9.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c9 img { + width: 24px; +} + +.c6 { + padding: 4px; +} + +.c3.MuiButton-root { + height: 32px; + font-size: 12px; + -webkit-letter-spacing: 1px; + -moz-letter-spacing: 1px; + -ms-letter-spacing: 1px; + letter-spacing: 1px; + line-height: 1; + border-radius: 2px; + font-weight: 600; +} + +.c3.MuiButton-outlined { + padding: 8px 12px; +} + +.c7.MuiFormControlLabel-root { + margin-right: 0; + margin-left: 0; +} + +.c7 .MuiFormControlLabel-label { + color: #1a1a1a; +} + +.c7 .MuiFormControlLabel-label.Mui-disabled { + color: #d8d8d8; +} + +.c7 .MuiTypography-root { + margin-left: 8px; +} + +.c8.MuiButton-root { + border-radius: 50%; + min-width: 32px; + height: 32px; + padding: 0; +} + +.c8.MuiButton-root:disabled svg { + fill: #d8d8d8; +} + +.c8.MuiButton-root:hover { + background-color: rgba(0,179,236,0.1); +} + +.c8.MuiButton-text { + padding: 0; +} + +.c1 .sync-icon-button { + text-transform: uppercase; + pointer-events: none; +} + +.c1 .rotate-icon { + color: #009CCC; + -webkit-animation: 1s linear infinite dxlcOg; + animation: 1s linear infinite dxlcOg; +} + +.c2 { + width: 50%; + min-width: -webkit-fit-content; + min-width: -moz-fit-content; + min-width: fit-content; +} + +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+`; + +exports[`SyncActions snapshots suspended 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c5 svg { + height: 24px; + width: 24px; +} + +.c5 svg path.path-fill, +.c5 svg line.path-fill, +.c5 svg polygon.path-fill, +.c5 svg rect.path-fill, +.c5 svg circle.path-fill, +.c5 svg polyline.path-fill { + fill: !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c5 svg path.stroke-fill, +.c5 svg line.stroke-fill, +.c5 svg polygon.stroke-fill, +.c5 svg rect.stroke-fill, +.c5 svg circle.stroke-fill, +.c5 svg polyline.stroke-fill { + stroke: !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c5 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c5.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c5.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c5 img { + width: 24px; +} + +.c9 svg { + fill: #009CCC; + height: 24px; + width: 24px; +} + +.c9 svg path.path-fill, +.c9 svg line.path-fill, +.c9 svg polygon.path-fill, +.c9 svg rect.path-fill, +.c9 svg circle.path-fill, +.c9 svg polyline.path-fill { + fill: #009CCC !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c9 svg path.stroke-fill, +.c9 svg line.stroke-fill, +.c9 svg polygon.stroke-fill, +.c9 svg rect.stroke-fill, +.c9 svg circle.stroke-fill, +.c9 svg polyline.stroke-fill { + stroke: #009CCC !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c9 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c9.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c9.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c9 img { + width: 24px; +} + +.c6 { + padding: 4px; +} + +.c3.MuiButton-root { + height: 32px; + font-size: 12px; + -webkit-letter-spacing: 1px; + -moz-letter-spacing: 1px; + -ms-letter-spacing: 1px; + letter-spacing: 1px; + line-height: 1; + border-radius: 2px; + font-weight: 600; +} + +.c3.MuiButton-outlined { + padding: 8px 12px; +} + +.c7.MuiFormControlLabel-root { + margin-right: 0; + margin-left: 0; +} + +.c7 .MuiFormControlLabel-label { + color: #1a1a1a; +} + +.c7 .MuiFormControlLabel-label.Mui-disabled { + color: #d8d8d8; +} + +.c7 .MuiTypography-root { + margin-left: 8px; +} + +.c8.MuiButton-root { + border-radius: 50%; + min-width: 32px; + height: 32px; + padding: 0; +} + +.c8.MuiButton-root:disabled svg { + fill: #d8d8d8; +} + +.c8.MuiButton-root:hover { + background-color: rgba(0,179,236,0.1); +} + +.c8.MuiButton-text { + padding: 0; +} + +.c1 .sync-icon-button { + text-transform: uppercase; + pointer-events: none; +} + +.c1 .rotate-icon { + color: #009CCC; + -webkit-animation: 1s linear infinite dxlcOg; + animation: 1s linear infinite dxlcOg; +} + +.c2 { + width: 50%; + min-width: -webkit-fit-content; + min-width: -moz-fit-content; + min-width: fit-content; +} + +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+`; diff --git a/ui/components/Sync/__tests__/__snapshots__/SyncControls.test.tsx.snap b/ui/components/Sync/__tests__/__snapshots__/SyncControls.test.tsx.snap new file mode 100644 index 00000000000..7d728a962bc --- /dev/null +++ b/ui/components/Sync/__tests__/__snapshots__/SyncControls.test.tsx.snap @@ -0,0 +1,2473 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SyncControls snapshots allButtonsDisabled 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c4 svg { + height: 24px; + width: 24px; +} + +.c4 svg path.path-fill, +.c4 svg line.path-fill, +.c4 svg polygon.path-fill, +.c4 svg rect.path-fill, +.c4 svg circle.path-fill, +.c4 svg polyline.path-fill { + fill: !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg path.stroke-fill, +.c4 svg line.stroke-fill, +.c4 svg polygon.stroke-fill, +.c4 svg rect.stroke-fill, +.c4 svg circle.stroke-fill, +.c4 svg polyline.stroke-fill { + stroke: !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c4.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c4.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c4 img { + width: 24px; +} + +.c8 svg { + fill: #009CCC; + height: 24px; + width: 24px; +} + +.c8 svg path.path-fill, +.c8 svg line.path-fill, +.c8 svg polygon.path-fill, +.c8 svg rect.path-fill, +.c8 svg circle.path-fill, +.c8 svg polyline.path-fill { + fill: #009CCC !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c8 svg path.stroke-fill, +.c8 svg line.stroke-fill, +.c8 svg polygon.stroke-fill, +.c8 svg rect.stroke-fill, +.c8 svg circle.stroke-fill, +.c8 svg polyline.stroke-fill { + stroke: #009CCC !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c8 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c8.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c8.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c8 img { + width: 24px; +} + +.c5 { + padding: 4px; +} + +.c2.MuiButton-root { + height: 32px; + font-size: 12px; + -webkit-letter-spacing: 1px; + -moz-letter-spacing: 1px; + -ms-letter-spacing: 1px; + letter-spacing: 1px; + line-height: 1; + border-radius: 2px; + font-weight: 600; +} + +.c2.MuiButton-outlined { + padding: 8px 12px; +} + +.c6.MuiFormControlLabel-root { + margin-right: 0; + margin-left: 0; +} + +.c6 .MuiFormControlLabel-label { + color: #1a1a1a; +} + +.c6 .MuiFormControlLabel-label.Mui-disabled { + color: #d8d8d8; +} + +.c6 .MuiTypography-root { + margin-left: 8px; +} + +.c7.MuiButton-root { + border-radius: 50%; + min-width: 32px; + height: 32px; + padding: 0; +} + +.c7.MuiButton-root:disabled svg { + fill: #d8d8d8; +} + +.c7.MuiButton-root:hover { + background-color: rgba(0,179,236,0.1); +} + +.c7.MuiButton-text { + padding: 0; +} + +.c1 .sync-icon-button { + text-transform: uppercase; + pointer-events: none; +} + +.c1 .rotate-icon { + color: #009CCC; + -webkit-animation: 1s linear infinite dxlcOg; + animation: 1s linear infinite dxlcOg; +} + +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+`; + +exports[`SyncControls snapshots hasTooltipSuffix 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c4 svg { + height: 24px; + width: 24px; +} + +.c4 svg path.path-fill, +.c4 svg line.path-fill, +.c4 svg polygon.path-fill, +.c4 svg rect.path-fill, +.c4 svg circle.path-fill, +.c4 svg polyline.path-fill { + fill: !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg path.stroke-fill, +.c4 svg line.stroke-fill, +.c4 svg polygon.stroke-fill, +.c4 svg rect.stroke-fill, +.c4 svg circle.stroke-fill, +.c4 svg polyline.stroke-fill { + stroke: !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c4.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c4.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c4 img { + width: 24px; +} + +.c8 svg { + fill: #009CCC; + height: 24px; + width: 24px; +} + +.c8 svg path.path-fill, +.c8 svg line.path-fill, +.c8 svg polygon.path-fill, +.c8 svg rect.path-fill, +.c8 svg circle.path-fill, +.c8 svg polyline.path-fill { + fill: #009CCC !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c8 svg path.stroke-fill, +.c8 svg line.stroke-fill, +.c8 svg polygon.stroke-fill, +.c8 svg rect.stroke-fill, +.c8 svg circle.stroke-fill, +.c8 svg polyline.stroke-fill { + stroke: #009CCC !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c8 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c8.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c8.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c8 img { + width: 24px; +} + +.c5 { + padding: 4px; +} + +.c2.MuiButton-root { + height: 32px; + font-size: 12px; + -webkit-letter-spacing: 1px; + -moz-letter-spacing: 1px; + -ms-letter-spacing: 1px; + letter-spacing: 1px; + line-height: 1; + border-radius: 2px; + font-weight: 600; +} + +.c2.MuiButton-outlined { + padding: 8px 12px; +} + +.c6.MuiFormControlLabel-root { + margin-right: 0; + margin-left: 0; +} + +.c6 .MuiFormControlLabel-label { + color: #1a1a1a; +} + +.c6 .MuiFormControlLabel-label.Mui-disabled { + color: #d8d8d8; +} + +.c6 .MuiTypography-root { + margin-left: 8px; +} + +.c7.MuiButton-root { + border-radius: 50%; + min-width: 32px; + height: 32px; + padding: 0; +} + +.c7.MuiButton-root:disabled svg { + fill: #d8d8d8; +} + +.c7.MuiButton-root:hover { + background-color: rgba(0,179,236,0.1); +} + +.c7.MuiButton-text { + padding: 0; +} + +.c1 .sync-icon-button { + text-transform: uppercase; + pointer-events: none; +} + +.c1 .rotate-icon { + color: #009CCC; + -webkit-animation: 1s linear infinite dxlcOg; + animation: 1s linear infinite dxlcOg; +} + +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+`; + +exports[`SyncControls snapshots hideSuspend 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c4 svg { + height: 24px; + width: 24px; +} + +.c4 svg path.path-fill, +.c4 svg line.path-fill, +.c4 svg polygon.path-fill, +.c4 svg rect.path-fill, +.c4 svg circle.path-fill, +.c4 svg polyline.path-fill { + fill: !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg path.stroke-fill, +.c4 svg line.stroke-fill, +.c4 svg polygon.stroke-fill, +.c4 svg rect.stroke-fill, +.c4 svg circle.stroke-fill, +.c4 svg polyline.stroke-fill { + stroke: !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c4.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c4.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c4 img { + width: 24px; +} + +.c5 { + padding: 4px; +} + +.c2.MuiButton-root { + height: 32px; + font-size: 12px; + -webkit-letter-spacing: 1px; + -moz-letter-spacing: 1px; + -ms-letter-spacing: 1px; + letter-spacing: 1px; + line-height: 1; + border-radius: 2px; + font-weight: 600; +} + +.c2.MuiButton-outlined { + padding: 8px 12px; +} + +.c6.MuiFormControlLabel-root { + margin-right: 0; + margin-left: 0; +} + +.c6 .MuiFormControlLabel-label { + color: #1a1a1a; +} + +.c6 .MuiFormControlLabel-label.Mui-disabled { + color: #d8d8d8; +} + +.c6 .MuiTypography-root { + margin-left: 8px; +} + +.c7.MuiButton-root { + border-radius: 50%; + min-width: 32px; + height: 32px; + padding: 0; +} + +.c7.MuiButton-root:disabled svg { + fill: #d8d8d8; +} + +.c7.MuiButton-root:hover { + background-color: rgba(0,179,236,0.1); +} + +.c7.MuiButton-text { + padding: 0; +} + +.c1 .sync-icon-button { + text-transform: uppercase; + pointer-events: none; +} + +.c1 .rotate-icon { + color: #009CCC; + -webkit-animation: 1s linear infinite dxlcOg; + animation: 1s linear infinite dxlcOg; +} + +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+`; + +exports[`SyncControls snapshots hideSyncOptions 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c4 svg { + height: 24px; + width: 24px; +} + +.c4 svg path.path-fill, +.c4 svg line.path-fill, +.c4 svg polygon.path-fill, +.c4 svg rect.path-fill, +.c4 svg circle.path-fill, +.c4 svg polyline.path-fill { + fill: !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg path.stroke-fill, +.c4 svg line.stroke-fill, +.c4 svg polygon.stroke-fill, +.c4 svg rect.stroke-fill, +.c4 svg circle.stroke-fill, +.c4 svg polyline.stroke-fill { + stroke: !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c4.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c4.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c4 img { + width: 24px; +} + +.c7 svg { + fill: #009CCC; + height: 24px; + width: 24px; +} + +.c7 svg path.path-fill, +.c7 svg line.path-fill, +.c7 svg polygon.path-fill, +.c7 svg rect.path-fill, +.c7 svg circle.path-fill, +.c7 svg polyline.path-fill { + fill: #009CCC !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c7 svg path.stroke-fill, +.c7 svg line.stroke-fill, +.c7 svg polygon.stroke-fill, +.c7 svg rect.stroke-fill, +.c7 svg circle.stroke-fill, +.c7 svg polyline.stroke-fill { + stroke: #009CCC !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c7 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c7.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c7.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c7 img { + width: 24px; +} + +.c5 { + padding: 4px; +} + +.c2.MuiButton-root { + height: 32px; + font-size: 12px; + -webkit-letter-spacing: 1px; + -moz-letter-spacing: 1px; + -ms-letter-spacing: 1px; + letter-spacing: 1px; + line-height: 1; + border-radius: 2px; + font-weight: 600; +} + +.c2.MuiButton-outlined { + padding: 8px 12px; +} + +.c6.MuiButton-root { + border-radius: 50%; + min-width: 32px; + height: 32px; + padding: 0; +} + +.c6.MuiButton-root:disabled svg { + fill: #d8d8d8; +} + +.c6.MuiButton-root:hover { + background-color: rgba(0,179,236,0.1); +} + +.c6.MuiButton-text { + padding: 0; +} + +.c1 .sync-icon-button { + text-transform: uppercase; + pointer-events: none; +} + +.c1 .rotate-icon { + color: #009CCC; + -webkit-animation: 1s linear infinite dxlcOg; + animation: 1s linear infinite dxlcOg; +} + +
+ +
+
+ +
+
+
+ +
+
+
+ +
+
+`; + +exports[`SyncControls snapshots non-suspended 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.c4 svg { + height: 24px; + width: 24px; +} + +.c4 svg path.path-fill, +.c4 svg line.path-fill, +.c4 svg polygon.path-fill, +.c4 svg rect.path-fill, +.c4 svg circle.path-fill, +.c4 svg polyline.path-fill { + fill: !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg path.stroke-fill, +.c4 svg line.stroke-fill, +.c4 svg polygon.stroke-fill, +.c4 svg rect.stroke-fill, +.c4 svg circle.stroke-fill, +.c4 svg polyline.stroke-fill { + stroke: !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c4 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c4.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c4.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c4 img { + width: 24px; +} + +.c8 svg { + fill: #009CCC; + height: 24px; + width: 24px; +} + +.c8 svg path.path-fill, +.c8 svg line.path-fill, +.c8 svg polygon.path-fill, +.c8 svg rect.path-fill, +.c8 svg circle.path-fill, +.c8 svg polyline.path-fill { + fill: #009CCC !important; + -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c8 svg path.stroke-fill, +.c8 svg line.stroke-fill, +.c8 svg polygon.stroke-fill, +.c8 svg rect.stroke-fill, +.c8 svg circle.stroke-fill, +.c8 svg polyline.stroke-fill { + stroke: #009CCC !important; + -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; + transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; +} + +.c8 svg rect.rect-height { + height: 24px; + width: 24px; +} + +.c8.downward { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.c8.upward { + -webkit-transform: initial; + -ms-transform: initial; + transform: initial; +} + +.c8 img { + width: 24px; +} + +.c5 { + padding: 4px; +} + +.c2.MuiButton-root { + height: 32px; + font-size: 12px; + -webkit-letter-spacing: 1px; + -moz-letter-spacing: 1px; + -ms-letter-spacing: 1px; + letter-spacing: 1px; + line-height: 1; + border-radius: 2px; + font-weight: 600; +} + +.c2.MuiButton-outlined { + padding: 8px 12px; +} + +.c6.MuiFormControlLabel-root { + margin-right: 0; + margin-left: 0; +} + +.c6 .MuiFormControlLabel-label { + color: #1a1a1a; +} + +.c6 .MuiFormControlLabel-label.Mui-disabled { + color: #d8d8d8; +} + +.c6 .MuiTypography-root { + margin-left: 8px; +} + +.c7.MuiButton-root { + border-radius: 50%; + min-width: 32px; + height: 32px; + padding: 0; +} + +.c7.MuiButton-root:disabled svg { + fill: #d8d8d8; +} + +.c7.MuiButton-root:hover { + background-color: rgba(0,179,236,0.1); +} + +.c7.MuiButton-text { + padding: 0; +} + +.c1 .sync-icon-button { + text-transform: uppercase; + pointer-events: none; +} + +.c1 .rotate-icon { + color: #009CCC; + -webkit-animation: 1s linear infinite dxlcOg; + animation: 1s linear infinite dxlcOg; +} + +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+`; diff --git a/ui/components/SyncActions.tsx b/ui/components/SyncActions.tsx deleted file mode 100644 index c883c9938db..00000000000 --- a/ui/components/SyncActions.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from "react"; -import styled from "styled-components"; -import { useSyncFluxObject } from "../hooks/automations"; -import { useToggleSuspend } from "../hooks/flux"; -import { Kind } from "../lib/api/core/types.pb"; -import Button from "./Button"; -import CustomActions from "./CustomActions"; -import Flex from "./Flex"; -import SyncButton from "./SyncButton"; - -interface Props { - name?: string; - namespace?: string; - clusterName?: string; - kind?: Kind; - suspended?: boolean; - hideDropdown?: boolean; - customActions?: JSX.Element[]; - className?: string; -} - -const SyncActions = ({ - name, - namespace, - clusterName, - kind, - suspended, - hideDropdown, - customActions, - className, -}: Props) => { - const suspend = useToggleSuspend( - { - objects: [ - { - name, - namespace, - clusterName, - kind: kind, - }, - ], - suspend: !suspended, - }, - "object" - ); - - const sync = useSyncFluxObject([ - { - name, - namespace, - clusterName, - kind: kind, - }, - ]); - - const syncHandler = hideDropdown - ? () => sync.mutateAsync({ withSource: false }) - : (opts) => sync.mutateAsync(opts); - - return ( - - - - - - ); -}; - -export default styled(SyncActions)` - width: 50%; - min-width: fit-content; -`; diff --git a/ui/components/SyncButton.tsx b/ui/components/SyncButton.tsx deleted file mode 100644 index 3ae7dec5a4d..00000000000 --- a/ui/components/SyncButton.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import * as React from "react"; -import styled from "styled-components"; -import Button, { IconButton } from "./Button"; -import Flex from "./Flex"; -import Icon, { IconType } from "./Icon"; - -type Props = { - className?: string; - loading?: boolean; - disabled?: boolean; - onClick: (opts: { withSource: boolean }) => void; - hideDropdown?: boolean; -}; - -export const ArrowDropDown = styled(IconButton)` - &.MuiButton-outlined { - //2px = MUI radius - border-radius: 0 2px 2px 0; - } - &.MuiButton-outlinedPrimary { - border-color: ${(props) => props.theme.colors.neutral20}; - } - &.MuiButton-root { - min-width: 0; - height: 32px; - padding: 8px 4px; - } - &.MuiButton-text { - padding: 0; - } -`; - -const Sync = styled(Button)<{ $hideDropdown: boolean }>` - &.MuiButton-outlined { - margin-right: 0; - ${(props) => - !props.$hideDropdown && - `border-radius: 2px 0 0 2px; border-right: none; &.MuiButton-outlined.Mui-disabled { - border-right: none };`} - } -`; - -export const DropDown = styled(Flex)` - position: absolute; - overflow: hidden; - background: ${(props) => props.theme.colors.neutral00}; - height: ${(props) => (props.open ? "100%" : "0px")}; - transition-property: height; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - z-index: 1; -`; - -function SyncButton({ - className, - loading, - disabled, - onClick, - hideDropdown = false, -}: Props) { - const [open, setOpen] = React.useState(false); - let arrowDropDown; - if (hideDropdown == false) { - arrowDropDown = ( - setOpen(!open)} - disabled={disabled} - > - - - ); - } else { - arrowDropDown = <>; - } - return ( -
- - onClick({ withSource: true })} - //$ - transient prop that is not passed to DOM https://styled-components.com/docs/api#transient-props - $hideDropdown={hideDropdown} - > - Sync - - {arrowDropDown} - - - - -
- ); -} - -export default styled(SyncButton).attrs({ className: SyncButton.name })``; diff --git a/ui/components/__tests__/__snapshots__/SyncActions.test.tsx.snap b/ui/components/__tests__/__snapshots__/SyncActions.test.tsx.snap deleted file mode 100644 index 670a346298b..00000000000 --- a/ui/components/__tests__/__snapshots__/SyncActions.test.tsx.snap +++ /dev/null @@ -1,803 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SyncActions snapshots hideDropdown 1`] = ` -.c0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-align-items: start; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: start; - gap: 12px; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c2 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-align-items: start; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: start; -} - -.c3.MuiButton-root { - height: 32px; - font-size: 12px; - -webkit-letter-spacing: 1px; - -moz-letter-spacing: 1px; - -ms-letter-spacing: 1px; - letter-spacing: 1px; - line-height: 1; - border-radius: 2px; - font-weight: 600; -} - -.c3.MuiButton-outlined { - padding: 8px 12px; -} - -.c4.MuiButton-outlined { - margin-right: 0; -} - -.c5 { - position: absolute; - overflow: hidden; - background: #ffffff; - height: 0px; - -webkit-transition-property: height; - transition-property: height; - -webkit-transition-duration: 0.2s; - transition-duration: 0.2s; - -webkit-transition-timing-function: ease-in-out; - transition-timing-function: ease-in-out; - z-index: 1; -} - -.c1 { - width: 50%; - min-width: -webkit-fit-content; - min-width: -moz-fit-content; - min-width: fit-content; -} - -
-
-
- -
-
- -
-
- -
-`; - -exports[`SyncActions snapshots non-suspended 1`] = ` -.c0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-align-items: start; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: start; - gap: 12px; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c2 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-align-items: start; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: start; -} - -.c7 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.c8 svg { - height: 16px; - width: 16px; -} - -.c8 svg path.path-fill, -.c8 svg line.path-fill, -.c8 svg polygon.path-fill, -.c8 svg rect.path-fill, -.c8 svg circle.path-fill, -.c8 svg polyline.path-fill { - fill: !important; - -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; - transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; -} - -.c8 svg path.stroke-fill, -.c8 svg line.stroke-fill, -.c8 svg polygon.stroke-fill, -.c8 svg rect.stroke-fill, -.c8 svg circle.stroke-fill, -.c8 svg polyline.stroke-fill { - stroke: !important; - -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; - transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; -} - -.c8 svg rect.rect-height { - height: 16px; - width: 16px; -} - -.c8.downward { - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} - -.c8.upward { - -webkit-transform: initial; - -ms-transform: initial; - transform: initial; -} - -.c8 img { - width: 16px; -} - -.c3.MuiButton-root { - height: 32px; - font-size: 12px; - -webkit-letter-spacing: 1px; - -moz-letter-spacing: 1px; - -ms-letter-spacing: 1px; - letter-spacing: 1px; - line-height: 1; - border-radius: 2px; - font-weight: 600; -} - -.c3.MuiButton-outlined { - padding: 8px 12px; -} - -.c5.MuiButton-root { - border-radius: 50%; - min-width: 38px; - height: 38px; - padding: 0; -} - -.c5.MuiButton-text { - padding: 0; -} - -.c6.MuiButton-outlined { - border-radius: 0 2px 2px 0; -} - -.c6.MuiButton-outlinedPrimary { - border-color: #d8d8d8; -} - -.c6.MuiButton-root { - min-width: 0; - height: 32px; - padding: 8px 4px; -} - -.c6.MuiButton-text { - padding: 0; -} - -.c4.MuiButton-outlined { - margin-right: 0; - border-radius: 2px 0 0 2px; - border-right: none; -} - -.c4.MuiButton-outlined.MuiButton-outlined.Mui-disabled { - border-right: none; -} - -.c9 { - position: absolute; - overflow: hidden; - background: #ffffff; - height: 0px; - -webkit-transition-property: height; - transition-property: height; - -webkit-transition-duration: 0.2s; - transition-duration: 0.2s; - -webkit-transition-timing-function: ease-in-out; - transition-timing-function: ease-in-out; - z-index: 1; -} - -.c1 { - width: 50%; - min-width: -webkit-fit-content; - min-width: -moz-fit-content; - min-width: fit-content; -} - -
-
-
- - -
-
- -
-
- -
-`; - -exports[`SyncActions snapshots suspended 1`] = ` -.c0 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-align-items: start; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: start; - gap: 12px; - -webkit-box-pack: start; - -webkit-justify-content: flex-start; - -ms-flex-pack: start; - justify-content: flex-start; -} - -.c2 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-align-items: start; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: start; -} - -.c7 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.c8 svg { - height: 16px; - width: 16px; -} - -.c8 svg path.path-fill, -.c8 svg line.path-fill, -.c8 svg polygon.path-fill, -.c8 svg rect.path-fill, -.c8 svg circle.path-fill, -.c8 svg polyline.path-fill { - fill: !important; - -webkit-transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; - transition: fill 200ms cubic-bezier(0.4,0,0.2,1) 0ms; -} - -.c8 svg path.stroke-fill, -.c8 svg line.stroke-fill, -.c8 svg polygon.stroke-fill, -.c8 svg rect.stroke-fill, -.c8 svg circle.stroke-fill, -.c8 svg polyline.stroke-fill { - stroke: !important; - -webkit-transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; - transition: stroke 200ms cubic-bezier(0.4,0,0.2,1) 0ms; -} - -.c8 svg rect.rect-height { - height: 16px; - width: 16px; -} - -.c8.downward { - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} - -.c8.upward { - -webkit-transform: initial; - -ms-transform: initial; - transform: initial; -} - -.c8 img { - width: 16px; -} - -.c3.MuiButton-root { - height: 32px; - font-size: 12px; - -webkit-letter-spacing: 1px; - -moz-letter-spacing: 1px; - -ms-letter-spacing: 1px; - letter-spacing: 1px; - line-height: 1; - border-radius: 2px; - font-weight: 600; -} - -.c3.MuiButton-outlined { - padding: 8px 12px; -} - -.c5.MuiButton-root { - border-radius: 50%; - min-width: 38px; - height: 38px; - padding: 0; -} - -.c5.MuiButton-text { - padding: 0; -} - -.c6.MuiButton-outlined { - border-radius: 0 2px 2px 0; -} - -.c6.MuiButton-outlinedPrimary { - border-color: #d8d8d8; -} - -.c6.MuiButton-root { - min-width: 0; - height: 32px; - padding: 8px 4px; -} - -.c6.MuiButton-text { - padding: 0; -} - -.c4.MuiButton-outlined { - margin-right: 0; - border-radius: 2px 0 0 2px; - border-right: none; -} - -.c4.MuiButton-outlined.MuiButton-outlined.Mui-disabled { - border-right: none; -} - -.c9 { - position: absolute; - overflow: hidden; - background: #ffffff; - height: 0px; - -webkit-transition-property: height; - transition-property: height; - -webkit-transition-duration: 0.2s; - transition-duration: 0.2s; - -webkit-transition-timing-function: ease-in-out; - transition-timing-function: ease-in-out; - z-index: 1; -} - -.c1 { - width: 50%; - min-width: -webkit-fit-content; - min-width: -moz-fit-content; - min-width: fit-content; -} - -
-
-
- - -
-
- -
-
- -
-`; diff --git a/ui/index.ts b/ui/index.ts index b3a45b8affa..236838c2a7b 100644 --- a/ui/index.ts +++ b/ui/index.ts @@ -70,7 +70,7 @@ import SourceLink from "./components/SourceLink"; import SourcesTable from "./components/SourcesTable"; import Spacer from "./components/Spacer"; import SubRouterTabs, { RouterTab } from "./components/SubRouterTabs"; -import SyncButton from "./components/SyncButton"; +import SyncControls from "./components/Sync/SyncControls"; import Text from "./components/Text"; import Timestamp from "./components/Timestamp"; import UserGroupsTable from "./components/UserGroupsTable"; @@ -240,7 +240,7 @@ export { SourcesTable, Spacer, SubRouterTabs, - SyncButton, + SyncControls, Text, ThemeTypes, Timestamp, diff --git a/ui/lib/theme.ts b/ui/lib/theme.ts index b0f659d87d9..6ec98571a57 100644 --- a/ui/lib/theme.ts +++ b/ui/lib/theme.ts @@ -1,5 +1,6 @@ // Typescript will handle type-checking/linting for this file import { createTheme } from "@material-ui/core"; +import { alpha } from "@material-ui/core/styles/colorManipulator"; // eslint-disable-next-line import { createGlobalStyle, DefaultTheme } from "styled-components"; import { ThemeTypes } from "../contexts/AppContext"; @@ -274,5 +275,32 @@ export const muiTheme = (colors, mode) => }, }, }, + // radio buttons + MuiRadio: { + root: { + padding: 0, + color: colors.primary30, + }, + + colorSecondary: { + color: colors.primary30, + + "&:hover": { + backgroundColor: ThemeTypes.Dark + ? alpha(colors.primary10, 0.2) + : alpha(colors.primary, 0.1), + color: colors.primary10, + }, + + "&$checked": { + color: colors.primary10, + }, + + "&$disabled": { + color: + mode === ThemeTypes.Dark ? colors.primary30 : colors.neutral20, + }, + }, + }, }, });