diff --git a/package.json b/package.json index 8b6121066..240b6bff1 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "cypress:run": "cypress run", "gen": "run-p gen:*", "gen:gql": "graphql-codegen --config codegen.yml", - "gen:i18n": "extract-messages -d en -l=en,ja -o translations -f yaml 'src/**/*.tsx' --extractFromFormatMessageCall", + "gen:i18n": "extract-messages -d en -l=en,ja -o translations -f yaml 'src/**/*.ts*' --extractFromFormatMessageCall", "gen:doc:plugin": "ts-node -O '{\"module\":\"CommonJS\"}' ./bin/pluginDoc" }, "engines": { @@ -204,4 +204,4 @@ "use-debounce": "^5.2.0", "use-file-input": "^1.0.0" } -} +} \ No newline at end of file diff --git a/src/app.tsx b/src/app.tsx index d8f5dd1c9..437e50097 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -2,6 +2,7 @@ import { Router, Redirect } from "@reach/router"; import React, { Suspense } from "react"; import Loading from "@reearth/components/atoms/Loading"; +import NotificationBanner from "@reearth/components/organisms/Notification"; import NotFound from "@reearth/components/pages/NotFound"; import AccountSettings from "@reearth/components/pages/Settings/Account"; import ProjectSettings from "@reearth/components/pages/Settings/Project"; @@ -42,6 +43,7 @@ const App: React.FC = () => { }> + diff --git a/src/components/atoms/Notification/index.stories.tsx b/src/components/atoms/Notification/index.stories.tsx new file mode 100644 index 000000000..4cfa1d726 --- /dev/null +++ b/src/components/atoms/Notification/index.stories.tsx @@ -0,0 +1,50 @@ +import { Meta } from "@storybook/react"; +import React from "react"; + +import Notification from "."; + +export default { + title: "atoms/NotificationBanner", + component: Notification, +} as Meta; + +export const Success = () => ( + +); +export const Error = () => ( + +); +export const Warning = () => ( + +); +export const Info = () => ( + +); diff --git a/src/components/atoms/Notification/index.test.tsx b/src/components/atoms/Notification/index.test.tsx new file mode 100644 index 000000000..353b6e172 --- /dev/null +++ b/src/components/atoms/Notification/index.test.tsx @@ -0,0 +1,30 @@ +import React from "react"; + +import { render, screen } from "@reearth/test/utils"; + +import NotificationBanner, { Notification } from "."; + +const sampleNotification: Notification = { + type: "info", + heading: "Notice", + text: "This is a notification for something super cool.", +}; + +test("Notification component should be rendered", () => { + render(); +}); + +test("Notification component should display notification heading", () => { + render(); + expect(screen.getByText(/Notice/)).toBeInTheDocument(); +}); + +test("Notification component should display notification text", () => { + render(); + expect(screen.getByText(/This is a notification/)).toBeInTheDocument(); +}); + +test("Notification component should not display anything", () => { + render(); + expect(screen.getByText(/This is a notification/)).not.toBeVisible(); +}); diff --git a/src/components/atoms/Notification/index.tsx b/src/components/atoms/Notification/index.tsx new file mode 100644 index 000000000..ae410bb79 --- /dev/null +++ b/src/components/atoms/Notification/index.tsx @@ -0,0 +1,88 @@ +import React from "react"; + +import Flex from "@reearth/components/atoms/Flex"; +import Icon from "@reearth/components/atoms/Icon"; +import Text from "@reearth/components/atoms/Text"; +import { styled, metrics, useTheme } from "@reearth/theme"; + +export type NotificationType = "error" | "warning" | "info" | "success"; +export type Notification = { + type: NotificationType; + heading?: string; + text: string; +}; + +export type Props = { + visible?: boolean; + setModal?: (show: boolean) => void; + notification?: Notification; + resetNotification?: () => void; +}; + +const NotificationBanner: React.FC = ({ + visible, + setModal, + notification, + resetNotification, +}) => { + const theme = useTheme(); + + return ( + + + + {notification?.heading} + + { + setModal?.(false); + resetNotification?.(); + }} + /> + + + {notification?.text} + + + ); +}; + +const StyledNotificationBanner = styled(Flex)<{ + type?: NotificationType; + visible?: boolean; +}>` + position: absolute; + top: ${metrics.headerHeight}px; + right: 0; + width: 312px; + padding: 8px 12px; + background-color: ${({ type, theme }) => + type === "error" + ? theme.notification.errorBg + : type === "warning" + ? theme.notification.warningBg + : type === "success" + ? theme.notification.successBg + : theme.notification.infoBg}; + color: ${({ theme }) => theme.notification.text}; + z-index: ${({ theme, visible }) => (visible ? theme.zIndexes.notificationBar : 0)}; + opacity: ${({ visible }) => (visible ? "1" : "0")}; + transition: all 0.5s; + pointer-event: ${({ visible }) => (visible ? "auto" : "none")}; +`; + +const HeadingArea = styled(Flex)` + width: 100%; +`; + +const CloseBtn = styled(Icon)` + cursor: pointer; +`; + +export default NotificationBanner; diff --git a/src/components/atoms/NotificationBar/README.md b/src/components/atoms/NotificationBar/README.md deleted file mode 100644 index 9488cf971..000000000 --- a/src/components/atoms/NotificationBar/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# NotificationBar -[![Generic badge](https://img.shields.io/badge/GROUP-global-.svg)]() -[![Generic badge](https://img.shields.io/badge/SIZE-atom-blue.svg)]() - -NotificationBar. This component is a global component. - -## Usage - -## Properties diff --git a/src/components/atoms/NotificationBar/index.stories.tsx b/src/components/atoms/NotificationBar/index.stories.tsx deleted file mode 100644 index 033e3b5d7..000000000 --- a/src/components/atoms/NotificationBar/index.stories.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Meta } from "@storybook/react"; -import React from "react"; - -import NotificationBar from "."; - -export default { - title: "atoms/NotificationBar", - component: NotificationBar, -} as Meta; - -export const Info = () => ; -export const Error = () => ; -export const Warning = () => ; diff --git a/src/components/atoms/NotificationBar/index.tsx b/src/components/atoms/NotificationBar/index.tsx deleted file mode 100644 index 036435be1..000000000 --- a/src/components/atoms/NotificationBar/index.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React, { useState, useEffect } from "react"; - -import Icon from "@reearth/components/atoms/Icon"; -import Text from "@reearth/components/atoms/Text"; -import { styled, useTheme } from "@reearth/theme"; - -export type Type = "error" | "warning" | "info" | "success"; - -interface NotificationBarProps { - text?: string; - hidden?: boolean; - type?: Type; - onClose?: () => void; -} - -const NotificationBar: React.FC = ({ - text, - hidden, - type, - children, - onClose, -}) => { - const [visibility, changeVisibility] = useState(!hidden); - useEffect(() => { - changeVisibility(!hidden); - }, [hidden, text]); - const theme = useTheme(); - - return visibility && (text || children) && type ? ( - - - {text || children} - - { - changeVisibility(false); - onClose?.(); - }} - /> - - ) : null; -}; - -const StyledNotificationBar = styled.div<{ - type?: Type; -}>` - width: 100%; - height: 40px; - display: flex; - justify-content: space-between; - align-items: center; - background-color: ${({ type, theme }) => - type === "error" - ? theme.notification.errorBg - : type === "warning" - ? theme.notification.warningBg - : type === "success" - ? theme.notification.successBg - : theme.notification.infoBg}; - color: ${({ theme }) => theme.notification.text}; - position: absolute; - top: 0; - z-index: ${props => props.theme.zIndexes.notificationBar}; -`; - -const CloseBtn = styled(Icon)` - padding: 10px; - cursor: pointer; -`; - -export default NotificationBar; diff --git a/src/components/molecules/Common/Header/index.tsx b/src/components/molecules/Common/Header/index.tsx index dbd974e5b..b5a65bf33 100644 --- a/src/components/molecules/Common/Header/index.tsx +++ b/src/components/molecules/Common/Header/index.tsx @@ -2,7 +2,6 @@ import { Link } from "@reach/router"; import React from "react"; import Icon from "@reearth/components/atoms/Icon"; -import NotificationBar, { Type } from "@reearth/components/atoms/NotificationBar"; import WorkspaceCreationModal from "@reearth/components/molecules/Common/WorkspaceCreationModal"; import { styled, metrics, css } from "@reearth/theme"; @@ -11,8 +10,6 @@ import { User, Team, Project } from "./types"; export * from "./types"; -export type NotificationType = Type; - export interface Props { className?: string; user?: User; @@ -31,11 +28,6 @@ export interface Props { modalShown?: boolean; openModal?: () => void; handleModalClose?: (r?: boolean | undefined) => void; - notification?: { - type?: NotificationType; - text: string; - }; - onNotificationClose?: () => void; dashboard?: boolean; } @@ -54,50 +46,39 @@ const Header: React.FC = ({ modalShown, openModal, handleModalClose, - notification, - onNotificationClose, dashboard, }) => { return ( - <> - - - - - {!dashboard && } - - {icon} - {onSignOut && onChangeTeam && ( - <> - - - - )} - - {center} - {right} - - - {notification && ( - - )} - + + + + + {!dashboard && } + + {icon} + {onSignOut && onChangeTeam && ( + <> + + + + )} + + {center} + {right} + + ); }; diff --git a/src/components/molecules/EarthEditor/DatasetPane/DatasetDeleteModal/index.tsx b/src/components/molecules/EarthEditor/DatasetPane/DatasetDeleteModal/index.tsx new file mode 100644 index 000000000..73c3c5909 --- /dev/null +++ b/src/components/molecules/EarthEditor/DatasetPane/DatasetDeleteModal/index.tsx @@ -0,0 +1,67 @@ +import React from "react"; +import { useIntl } from "react-intl"; + +import Button from "@reearth/components/atoms/Button"; +import Icon from "@reearth/components/atoms/Icon"; +import Modal from "@reearth/components/atoms/Modal"; +import Text from "@reearth/components/atoms/Text"; +import { styled, useTheme, metricsSizes } from "@reearth/theme"; + +export type Props = { + onRemove?: (schemaId?: string) => void; + setModal?: (show: boolean) => void; + openModal?: boolean; +}; + +const DatasetDeleteModal: React.FC = ({ onRemove, setModal, openModal }) => { + const intl = useIntl(); + const theme = useTheme(); + return ( + onRemove?.()} + /> + } + button2={ +