diff --git a/web/src/components/molecules/Accessibility/index.tsx b/web/src/components/molecules/Accessibility/index.tsx index c337145427..83765f16ec 100644 --- a/web/src/components/molecules/Accessibility/index.tsx +++ b/web/src/components/molecules/Accessibility/index.tsx @@ -10,6 +10,7 @@ import Input from "@reearth-cms/components/atoms/Input"; import Select from "@reearth-cms/components/atoms/Select"; import Switch from "@reearth-cms/components/atoms/Switch"; import Table, { TableColumnsType } from "@reearth-cms/components/atoms/Table"; +import Tooltip from "@reearth-cms/components/atoms/Tooltip"; import { PublicScope } from "@reearth-cms/components/molecules/Accessibility/types"; import { Model } from "@reearth-cms/components/molecules/Model/types"; import { useT } from "@reearth-cms/i18n"; @@ -154,7 +155,11 @@ const Accessibility: React.FC = ({ } + suffix={ + + + + } contentEditable={false} /> @@ -185,3 +190,11 @@ const StyledAnchor = styled.a` text-decoration: underline; color: #000000d9; `; + +const StyledIcon = styled(Icon)` + transition: all 0.3s; + color: rgb(0, 0, 0, 0.45); + :hover { + color: rgba(0, 0, 0, 0.88); + } +`; diff --git a/web/src/components/molecules/Asset/Asset/AssetBody/Asset.tsx b/web/src/components/molecules/Asset/Asset/AssetBody/Asset.tsx index 53fed16c27..e998212d6c 100644 --- a/web/src/components/molecules/Asset/Asset/AssetBody/Asset.tsx +++ b/web/src/components/molecules/Asset/Asset/AssetBody/Asset.tsx @@ -6,6 +6,7 @@ import Button from "@reearth-cms/components/atoms/Button"; import DownloadButton from "@reearth-cms/components/atoms/DownloadButton"; import Icon from "@reearth-cms/components/atoms/Icon"; import Space from "@reearth-cms/components/atoms/Space"; +import Tooltip from "@reearth-cms/components/atoms/Tooltip"; import UserAvatar from "@reearth-cms/components/atoms/UserAvatar"; import Card from "@reearth-cms/components/molecules/Asset/Asset/AssetBody/card"; import PreviewToolbar from "@reearth-cms/components/molecules/Asset/Asset/AssetBody/previewToolbar"; @@ -122,19 +123,20 @@ const AssetMolecule: React.FC = ({ } }, [assetFileExt, assetUrl, svgRender, viewerType, workspaceSettings]); + const handleCopy = useCallback(() => { + navigator.clipboard.writeText(asset.url); + }, [asset.url]); + return ( - {asset.fileName}{" "} - { - navigator.clipboard.writeText(asset.url); - }} - /> + {asset.fileName} + + + } toolbar={ @@ -203,10 +205,12 @@ const AssetMolecule: React.FC = ({ ); }; -const CopyIcon = styled(Icon)<{ selected?: boolean }>` - margin-left: 16px; - &:active { - color: #096dd9; +const CopyIcon = styled(Icon)` + margin-left: 10px; + transition: all 0.3s; + color: rgb(0, 0, 0, 0.45); + :hover { + color: rgba(0, 0, 0, 0.88); } `; diff --git a/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.test.ts b/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.test.ts index da0abd63ba..f5830054a8 100644 --- a/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.test.ts +++ b/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.test.ts @@ -1,4 +1,3 @@ -import { Key } from "rc-table/lib/interface"; import { expect, test } from "vitest"; import { AssetFile } from "@reearth-cms/components/molecules/Asset/types"; @@ -6,7 +5,7 @@ import { AssetFile } from "@reearth-cms/components/molecules/Asset/types"; import { generateAssetTreeData } from "./generateAssetTreeData"; test("returns empty array if filePaths property is not provided", () => { - const result = generateAssetTreeData({ name: "", path: "/" }, [], "http://example.com"); + const result = generateAssetTreeData({ name: "", path: "/" }); expect(result).toEqual([]); }); @@ -21,9 +20,7 @@ test("returns correct file tree data", () => { "/folder3/file4.txt", ], }; - const selectedKeys: Key[] = []; - const assetBaseUrl = "http://example.com"; - const result = generateAssetTreeData(file, selectedKeys, assetBaseUrl); + const result = generateAssetTreeData(file); // /folder1/ expect(result[0].key).toEqual("0-0"); diff --git a/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.tsx b/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.ts similarity index 52% rename from web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.tsx rename to web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.ts index b69dcd9f8e..cef8fd992d 100644 --- a/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.tsx +++ b/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/generateAssetTreeData.ts @@ -1,16 +1,8 @@ -import styled from "@emotion/styled"; -import { Key } from "rc-table/lib/interface"; - -import Icon from "@reearth-cms/components/atoms/Icon"; import { AssetFile } from "@reearth-cms/components/molecules/Asset/types"; import { FileNode } from "./types"; -export const generateAssetTreeData = ( - file: AssetFile, - selectedKeys: Key[], - assetBaseUrl: string, -): FileNode[] => { +export const generateAssetTreeData = (file: AssetFile): FileNode[] => { if (!file.filePaths) return []; const root: FileNode = { @@ -30,21 +22,10 @@ export const generateAssetTreeData = ( const key = `${i}-${j}`; const path = `${currentNode.path}${part}${/\.[^.]+$/.test(part) ? "" : "/"}`; const newNode: FileNode = { - key: key, - title: ( - <> - {part} - { - navigator.clipboard.writeText(assetBaseUrl + path); - }} - /> - - ), + key, + title: part, name: part, - path: path, + path, children: [], }; @@ -58,11 +39,3 @@ export const generateAssetTreeData = ( return root.children; }; - -const CopyIcon = styled(Icon)<{ selected?: boolean }>` - margin-left: 16px; - visibility: ${({ selected }) => (selected ? "visible" : "hidden")}; - &:active { - color: #096dd9; - } -`; diff --git a/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/index.tsx b/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/index.tsx index ccf13b7d12..6b21de1ba6 100644 --- a/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/index.tsx +++ b/web/src/components/molecules/Asset/Asset/AssetBody/UnzipFileList/index.tsx @@ -4,6 +4,7 @@ import { useCallback, useEffect, useState } from "react"; import Icon from "@reearth-cms/components/atoms/Icon"; import Spin from "@reearth-cms/components/atoms/Spin"; +import Tooltip from "@reearth-cms/components/atoms/Tooltip"; import Tree, { TreeProps } from "@reearth-cms/components/atoms/Tree"; import { ArchiveExtractionStatus, AssetFile } from "@reearth-cms/components/molecules/Asset/types"; import { useT } from "@reearth-cms/i18n"; @@ -26,14 +27,13 @@ const UnzipFileList: React.FC = ({ }) => { const t = useT(); - const [expandedKeys, setExpandedKeys] = useState(["0-0"]); const [selectedKeys, setSelectedKeys] = useState([]); - const [treeData, setTreeData] = useState([]); + const [treeData, setTreeData] = useState(); useEffect(() => { - const data = generateAssetTreeData(file, selectedKeys, assetBaseUrl); + const data = generateAssetTreeData(file); setTreeData(data); - }, [assetBaseUrl, file, selectedKeys]); + }, [file]); const previewFile = useCallback( (path: string) => { @@ -51,9 +51,12 @@ const UnzipFileList: React.FC = ({ [previewFile, selectedKeys], ); - const handleExpand: TreeProps["onExpand"] = (keys: Key[]) => { - setExpandedKeys([...keys]); - }; + const handleCopy = useCallback( + (path: string) => { + navigator.clipboard.writeText(assetBaseUrl + path); + }, + [assetBaseUrl], + ); return ( @@ -69,16 +72,29 @@ const UnzipFileList: React.FC = ({ ) : ( - } - expandedKeys={[...expandedKeys]} - selectedKeys={[...selectedKeys]} - onSelect={handleSelect} - onExpand={handleExpand} - treeData={treeData} - multiple={false} - showLine - /> + treeData && ( + } + defaultExpandedKeys={["0-0"]} + selectedKeys={selectedKeys} + onSelect={handleSelect} + treeData={treeData} + multiple={false} + showLine + titleRender={({ title, key, path }) => { + return ( + <> + {title} + {selectedKeys[0] === key && ( + + handleCopy(path)} /> + + )} + + ); + }} + /> + ) )} ); @@ -119,4 +135,13 @@ const ExtractionFailedText = styled.p` color: rgba(0, 0, 0, 0.85); `; +const CopyIcon = styled(Icon)` + margin-left: 6px; + transition: all 0.3s; + color: rgb(0, 0, 0, 0.45); + :hover { + color: rgba(0, 0, 0, 0.88); + } +`; + export default UnzipFileList; diff --git a/web/src/components/molecules/Common/Form/GeometryItem/index.tsx b/web/src/components/molecules/Common/Form/GeometryItem/index.tsx index 8cb5bcf1ce..cb41c0fbb1 100644 --- a/web/src/components/molecules/Common/Form/GeometryItem/index.tsx +++ b/web/src/components/molecules/Common/Form/GeometryItem/index.tsx @@ -23,6 +23,7 @@ import Icon from "@reearth-cms/components/atoms/Icon"; import mapPinFilled from "@reearth-cms/components/atoms/Icon/Icons/mapPinFilled.svg"; import Input from "@reearth-cms/components/atoms/Input"; import Modal from "@reearth-cms/components/atoms/Modal"; +import Tooltip from "@reearth-cms/components/atoms/Tooltip"; import Typography from "@reearth-cms/components/atoms/Typography"; import { ObjectSupportedType, @@ -267,7 +268,7 @@ const GeometryItem: React.FC = ({ }, [currentValue, typeCheck, value]); const placeholderContent = useMemo(() => { - const key = Array.isArray(supportedTypes) ? supportedTypes[0] : supportedTypes ?? "POINT"; + const key = Array.isArray(supportedTypes) ? supportedTypes[0] : (supportedTypes ?? "POINT"); const obj: { type: string; coordinates?: unknown; @@ -505,16 +506,20 @@ const GeometryItem: React.FC = ({ handle={}> - } - size="small" - onClick={copyButtonClick} - /> + + } + size="small" + onClick={copyButtonClick} + disabled={!currentValue} + /> + {!disabled && ( } size="small" onClick={deleteButtonClick} + disabled={!currentValue} /> )} diff --git a/web/src/components/molecules/MyIntegrations/Settings/Form.tsx b/web/src/components/molecules/MyIntegrations/Settings/Form.tsx index 085f2c421b..c5a3ea9cd6 100644 --- a/web/src/components/molecules/MyIntegrations/Settings/Form.tsx +++ b/web/src/components/molecules/MyIntegrations/Settings/Form.tsx @@ -1,5 +1,5 @@ import styled from "@emotion/styled"; -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useState } from "react"; import Button from "@reearth-cms/components/atoms/Button"; import Col from "@reearth-cms/components/atoms/Col"; @@ -10,6 +10,7 @@ import Input from "@reearth-cms/components/atoms/Input"; import Modal from "@reearth-cms/components/atoms/Modal"; import Row from "@reearth-cms/components/atoms/Row"; import TextArea from "@reearth-cms/components/atoms/TextArea"; +import Tooltip from "@reearth-cms/components/atoms/Tooltip"; import { Integration } from "@reearth-cms/components/molecules/MyIntegrations/types"; import { useT } from "@reearth-cms/i18n"; @@ -84,11 +85,8 @@ const MyIntegrationForm: React.FC = ({ }); }, [t, onRegenerateToken]); - const copyIcon = useMemo(() => { - const onClick = () => { - if (integration.config.token) navigator.clipboard.writeText(integration.config.token); - }; - return ; + const handleCopy = useCallback(() => { + if (integration.config.token) navigator.clipboard.writeText(integration.config.token); }, [integration.config.token]); return ( @@ -117,7 +115,11 @@ const MyIntegrationForm: React.FC = ({ + + + } />