diff --git a/frontend/webapp/components/modals/delete-warning/index.tsx b/frontend/webapp/components/modals/delete-warning/index.tsx index a3c2a654c..a95c1bb0b 100644 --- a/frontend/webapp/components/modals/delete-warning/index.tsx +++ b/frontend/webapp/components/modals/delete-warning/index.tsx @@ -1,21 +1,28 @@ import React from 'react'; import { WarningModal } from '@/reuseable-components'; +import { NotificationType } from '@/types'; interface Props { isOpen: boolean; noOverlay?: boolean; name?: string; + note?: { + type: NotificationType; + title: string; + message: string; + }; onApprove: () => void; onDeny: () => void; } -const DeleteWarning: React.FC = ({ isOpen, noOverlay, name, onApprove, onDeny }) => { +const DeleteWarning: React.FC = ({ isOpen, noOverlay, name, note, onApprove, onDeny }) => { return ( { - const { deleteSources } = useSourceCRUD(); + const { sources, deleteSources } = useSourceCRUD(); const { configuredSources, setConfiguredSources } = useAppStore((state) => state); const [isWarnModalOpen, setIsWarnModalOpen] = useState(false); @@ -70,7 +70,21 @@ const MultiSourceControl = () => { - setIsWarnModalOpen(false)} /> + setIsWarnModalOpen(false)} + /> ); }; diff --git a/frontend/webapp/containers/main/overview/overview-drawer/index.tsx b/frontend/webapp/containers/main/overview/overview-drawer/index.tsx index 5f646cbd9..6ab29ae62 100644 --- a/frontend/webapp/containers/main/overview/overview-drawer/index.tsx +++ b/frontend/webapp/containers/main/overview/overview-drawer/index.tsx @@ -5,8 +5,11 @@ import DrawerFooter from './drawer-footer'; import { Drawer } from '@/reuseable-components'; import DrawerHeader, { DrawerHeaderRef } from './drawer-header'; import { CancelWarning, DeleteWarning } from '@/components/modals'; +import { OVERVIEW_ENTITY_TYPES } from '@/types'; +import { useDestinationCRUD, useSourceCRUD } from '@/hooks'; -const DRAWER_WIDTH = '640px'; +// + 64 because of padding +const DRAWER_WIDTH = `${640 + 64}px`; interface Props { title: string; @@ -32,6 +35,8 @@ const ContentArea = styled.div` `; const OverviewDrawer: React.FC = ({ children, title, imageUri, isEdit, isFormDirty, onEdit, onSave, onDelete, onCancel }) => { + const { sources } = useSourceCRUD(); + const { destinations } = useDestinationCRUD(); const selectedItem = useDrawerStore(({ selectedItem }) => selectedItem); const setSelectedItem = useDrawerStore(({ setSelectedItem }) => setSelectedItem); @@ -80,6 +85,15 @@ const OverviewDrawer: React.FC = ({ children, title, onSave(titleRef.current?.getTitle() || ''); }; + const isLastItem = () => { + let isLast = false; + + if (selectedItem?.type === OVERVIEW_ENTITY_TYPES.SOURCE) isLast = sources.length === 1; + if (selectedItem?.type === OVERVIEW_ENTITY_TYPES.DESTINATION) isLast = destinations.length === 1; + + return isLast; + }; + return ( <> @@ -90,7 +104,22 @@ const OverviewDrawer: React.FC = ({ children, title, - + ); diff --git a/frontend/webapp/public/icons/notification/warning-icon2.svg b/frontend/webapp/public/icons/notification/warning-icon2.svg new file mode 100644 index 000000000..e6bd7a9e9 --- /dev/null +++ b/frontend/webapp/public/icons/notification/warning-icon2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/webapp/reuseable-components/divider/index.tsx b/frontend/webapp/reuseable-components/divider/index.tsx index 9d5aaa903..b941378b6 100644 --- a/frontend/webapp/reuseable-components/divider/index.tsx +++ b/frontend/webapp/reuseable-components/divider/index.tsx @@ -19,7 +19,7 @@ const StyledDivider = styled.div<{ width: ${({ $orientation, $thickness, $length }) => ($orientation === 'vertical' ? `${$thickness}px` : $length || '100%')}; height: ${({ $orientation, $thickness, $length }) => ($orientation === 'horizontal' ? `${$thickness}px` : $length || '100%')}; margin: ${({ $orientation, $margin }) => $margin || ($orientation === 'horizontal' ? '8px 0' : '0 8px')}; - background-color: ${({ color, theme }) => color || theme.colors.border}; + background-color: ${({ $color, theme }) => $color || theme.colors.border}; `; const Divider: React.FC = ({ orientation = 'horizontal', thickness = 1, length, color, margin }) => { diff --git a/frontend/webapp/reuseable-components/modal/warning-modal/index.tsx b/frontend/webapp/reuseable-components/modal/warning-modal/index.tsx index a3c9135a3..a21cc1231 100644 --- a/frontend/webapp/reuseable-components/modal/warning-modal/index.tsx +++ b/frontend/webapp/reuseable-components/modal/warning-modal/index.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import styled from 'styled-components'; -import { Button, ButtonProps, Modal, Text } from '@/reuseable-components'; import { useKeyDown } from '@/hooks'; +import styled from 'styled-components'; +import type { NotificationType } from '@/types'; +import { Button, ButtonProps, Modal, NotificationNote, Text } from '@/reuseable-components'; interface ButtonParams { text: string; @@ -14,6 +15,11 @@ interface Props { noOverlay?: boolean; title: string; description: string; + note?: { + type: NotificationType; + title: string; + message: string; + }; approveButton: ButtonParams; denyButton: ButtonParams; } @@ -46,20 +52,21 @@ const Footer = styled.div` `; const FooterButton = styled(Button)` - width: 224px; + width: 250px; `; -export const WarningModal: React.FC = ({ isOpen, noOverlay, title = '', description = '', approveButton, denyButton }) => { - useKeyDown( - { - key: 'Enter', - active: isOpen, - }, - () => approveButton.onClick() - ); +const NoteWrapper = styled.div` + margin-bottom: 12px; +`; + +export const WarningModal: React.FC = ({ isOpen, noOverlay, title = '', description = '', note, approveButton, denyButton }) => { + useKeyDown({ key: 'Enter', active: isOpen }, () => approveButton.onClick()); + + const onApprove = () => approveButton.onClick(); + const onDeny = () => denyButton.onClick(); return ( - + {title} @@ -67,11 +74,17 @@ export const WarningModal: React.FC = ({ isOpen, noOverlay, title = '', d {description} + {!!note && ( + + + + )} +
- + {approveButton.text} - + {denyButton.text}
diff --git a/frontend/webapp/reuseable-components/transition/index.tsx b/frontend/webapp/reuseable-components/transition/index.tsx index b9df86abb..75e0ad43d 100644 --- a/frontend/webapp/reuseable-components/transition/index.tsx +++ b/frontend/webapp/reuseable-components/transition/index.tsx @@ -1,4 +1,4 @@ -import React, { PropsWithChildren, useEffect, useMemo, useState } from 'react'; +import React, { PropsWithChildren, useEffect, useState } from 'react'; import styled from 'styled-components'; import type { IStyledComponentBase, Keyframes, Substitute } from 'styled-components/dist/types'; @@ -26,6 +26,8 @@ export const Transition: React.FC> = ({ container: Cont if (enter) setIsEntered(true); }, [enter]); + if (!enter && !isEntered) return null; + return ( {children} diff --git a/frontend/webapp/styles/styled.tsx b/frontend/webapp/styles/styled.tsx index d81c3e8ce..bfc3ecf3e 100644 --- a/frontend/webapp/styles/styled.tsx +++ b/frontend/webapp/styles/styled.tsx @@ -24,7 +24,7 @@ export const Overlay = styled.div` export const ModalBody = styled.div` width: 640px; height: calc(100vh - 300px); - margin: 0 15vw; + margin: 0 7vw; padding-top: 64px; overflow-y: scroll; `; diff --git a/frontend/webapp/utils/functions/icons.ts b/frontend/webapp/utils/functions/icons.ts index fddb81e85..17e8f727c 100644 --- a/frontend/webapp/utils/functions/icons.ts +++ b/frontend/webapp/utils/functions/icons.ts @@ -11,7 +11,7 @@ export const getStatusIcon = (status?: NotificationType) => { case 'error': return '/icons/notification/error-icon2.svg'; case 'warning': - return '/icons/notification/warning-icon.svg'; + return '/icons/notification/warning-icon2.svg'; case 'info': return '/icons/common/info.svg'; default: