From 6f60f535ffc94d6371c4f7678aa8a0d8b868d1b8 Mon Sep 17 00:00:00 2001 From: Casper Date: Tue, 19 Sep 2023 00:29:41 +0300 Subject: [PATCH] Preserve format when copy/paste yaml file (#4009) * Preserve format when copy/paste yaml file --- ui/components/CopyToCliboard.tsx | 29 +- ui/components/YamlView.tsx | 43 ++- .../__snapshots__/YamlView.test.tsx.snap | 274 +++++++++++------- 3 files changed, 211 insertions(+), 135 deletions(-) diff --git a/ui/components/CopyToCliboard.tsx b/ui/components/CopyToCliboard.tsx index 957c41c149..c0616fcf8d 100644 --- a/ui/components/CopyToCliboard.tsx +++ b/ui/components/CopyToCliboard.tsx @@ -1,29 +1,16 @@ import * as React from "react"; import { useCallback, useState } from "react"; -import styled from "styled-components"; -import { IconButton } from "./Button"; import Icon, { IconType } from "./Icon"; -const CopyButton = styled(IconButton)` - &.MuiButton-outlinedPrimary { - margin-left: ${(props) => props.theme.spacing.xxs}; - padding: ${(props) => props.theme.spacing.xxs}; - } - &.MuiButton-root { - height: initial; - width: initial; - min-width: 0px; - } -`; - export default function CopyToClipboard({ value, - className, size, + showText, }: { value: string; className?: string; - size?: "small" | "medium" | "large"; + size?: "small" | "base" | "medium" | "large"; + showText?: boolean; }) { const [copied, setCopied] = useState(false); const handleCopy = useCallback(() => { @@ -34,13 +21,17 @@ export default function CopyToClipboard({ }, 1500); }); }, [value]); - + let text = undefined; + if (showText) { + text = copied ? "Copied" : "Copy"; + } return ( - +
- +
); } diff --git a/ui/components/YamlView.tsx b/ui/components/YamlView.tsx index d0a9c2bd62..57dfa8dafe 100644 --- a/ui/components/YamlView.tsx +++ b/ui/components/YamlView.tsx @@ -7,6 +7,7 @@ import { useInDarkMode } from "../hooks/theme"; import { ObjectRef } from "../lib/api/core/types.pb"; import { createYamlCommand } from "../lib/utils"; import CopyToClipboard from "./CopyToCliboard"; +import Flex from "./Flex"; export type YamlViewProps = { className?: string; @@ -16,10 +17,9 @@ export type YamlViewProps = { theme?: ThemeTypes; }; -const YamlHeader = styled.div` +const YamlHeader = styled(Flex)` background: ${(props) => props.theme.colors.neutralGray}; padding: ${(props) => props.theme.spacing.small}; - width: 100%; border-bottom: 1px solid ${(props) => props.theme.colors.neutral20}; font-family: monospace; color: ${(props) => props.theme.colors.primary10}; @@ -53,7 +53,7 @@ function UnstyledYamlView({ }, }, - lineProps: { style: { flexWrap: "wrap" } }, + lineProps: { style: { textWrap: "wrap" } }, ...(dark && { style: darcula }), }; @@ -61,25 +61,29 @@ function UnstyledYamlView({ return (
{headerText && ( - + {headerText} )} - - {yaml} - +
+
+ +
+ + {yaml} + +
); } @@ -94,6 +98,17 @@ const YamlView = styled(UnstyledYamlView).attrs({ border-radius: 8px; overflow: hidden; + .code-wrapper { + position: relative; + } + .copy-wrapper { + position: absolute; + right: 4px; + top: 8px; + background: ${(props) => props.theme.colors.neutralGray}; + padding: 4px 8px; + border-radius: 2px; + } pre { padding: ${(props) => props.theme.spacing.medium} ${(props) => props.theme.spacing.small} !important; diff --git a/ui/components/__tests__/__snapshots__/YamlView.test.tsx.snap b/ui/components/__tests__/__snapshots__/YamlView.test.tsx.snap index 588f300def..91407f6c1b 100644 --- a/ui/components/__tests__/__snapshots__/YamlView.test.tsx.snap +++ b/ui/components/__tests__/__snapshots__/YamlView.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`YamlView snapshots renders 1`] = ` -.c4 { +.c1 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -13,13 +13,77 @@ exports[`YamlView snapshots renders 1`] = ` -webkit-box-align: center; -ms-flex-align: center; align-items: center; + gap: 4px; + width: 100%; } -.c5 svg { +.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: 12px; + width: 12px; +} + +.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: 12px; width: 12px; } +.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: 12px; +} + +.c5 svg { + height: 16px; + width: 16px; +} + .c5 svg path.path-fill, .c5 svg line.path-fill, .c5 svg polygon.path-fill, @@ -43,8 +107,8 @@ exports[`YamlView snapshots renders 1`] = ` } .c5 svg rect.rect-height { - height: 12px; - width: 12px; + height: 16px; + width: 16px; } .c5.downward { @@ -60,35 +124,12 @@ exports[`YamlView snapshots renders 1`] = ` } .c5 img { - width: 12px; -} - -.c2.MuiButton-root { - border-radius: 50%; - min-width: 38px; - height: 38px; - padding: 0; -} - -.c2.MuiButton-text { - padding: 0; -} - -.c3.MuiButton-outlinedPrimary { - margin-left: 4px; - padding: 4px; + width: 16px; } -.c3.MuiButton-root { - height: initial; - width: initial; - min-width: 0px; -} - -.c1 { +.c2 { background: #F6F7F9; padding: 12px; - width: 100%; border-bottom: 1px solid #d8d8d8; font-family: monospace; color: #009CCC; @@ -104,6 +145,19 @@ exports[`YamlView snapshots renders 1`] = ` overflow: hidden; } +.c0 .code-wrapper { + position: relative; +} + +.c0 .copy-wrapper { + position: absolute; + right: 4px; + top: 8px; + background: #F6F7F9; + padding: 4px 8px; + border-radius: 2px; +} + .c0 pre { padding: 24px 12px !important; } @@ -112,32 +166,49 @@ exports[`YamlView snapshots renders 1`] = ` className="c0 UnstyledYamlView" >
kubectl get kustomization podinfo -n flux-system -o yaml -
+ + +
+
+
- - -
-
-    
+    
+
-      
         
-          1
-        
-        
-          yaml\\nyaml\\nyaml\\n
+          
+            1
+          
+          
+            yaml\\nyaml\\nyaml\\n
+          
         
-      
-    
-  
+ + +
`;