Skip to content

Commit

Permalink
[GEN-1821]: "DrawerFooter" edits: text (uninstrument), animations (#1889
Browse files Browse the repository at this point in the history
)

This pull request includes updates to the `DeleteWarning` component and its usage across various parts of the frontend application. The changes focus on improving the handling of delete warnings, especially for the last items of certain types, and enhancing the `DrawerFooter` component.

Improvements to `DeleteWarning` component:

* [`frontend/webapp/components/modals/delete-warning/index.tsx`](diffhunk://#diff-4f8fac3da993d379d6710a6607b6f25708649cb2da5b4a5f433f8e62dde1d03fR2-R32): Updated the `DeleteWarning` component to accept `type` and `isLastItem` props, and modified the modal text accordingly.

Usage updates in different components:

* [`frontend/webapp/containers/main/destinations/add-destination/configured-destinations-list/index.tsx`](diffhunk://#diff-f5288a6a2e6ccce16445bdd7486abda1bbd12662ea0e0bc846ff0f60b85b12f9L5-R7): Updated the `DeleteWarning` usage to pass `type` and `isLastItem` props. [[1]](diffhunk://#diff-f5288a6a2e6ccce16445bdd7486abda1bbd12662ea0e0bc846ff0f60b85b12f9L5-R7) [[2]](diffhunk://#diff-f5288a6a2e6ccce16445bdd7486abda1bbd12662ea0e0bc846ff0f60b85b12f9L147-R148)
* [`frontend/webapp/containers/main/overview/multi-source-control/index.tsx`](diffhunk://#diff-cdd99a8fcd0484b24586f22b1f7b1bcf8d964bead53eeb0b2c07646c7301af70R4-R8): Modified the `DeleteWarning` usage to include `type` and `isLastItem` props, and adjusted the button text for uninstrumenting. [[1]](diffhunk://#diff-cdd99a8fcd0484b24586f22b1f7b1bcf8d964bead53eeb0b2c07646c7301af70R4-R8) [[2]](diffhunk://#diff-cdd99a8fcd0484b24586f22b1f7b1bcf8d964bead53eeb0b2c07646c7301af70L71-R84)
* [`frontend/webapp/containers/main/overview/overview-drawer/index.tsx`](diffhunk://#diff-732721edf7c32d883ffefa52d6e43339c6ee328c88c3cb5f0d87f6760347b599R48-R50): Updated the `DrawerFooter` and `DeleteWarning` usage to handle `type` and `isLastItem` props, and added conditional text for uninstrumenting sources. [[1]](diffhunk://#diff-732721edf7c32d883ffefa52d6e43339c6ee328c88c3cb5f0d87f6760347b599R48-R50) [[2]](diffhunk://#diff-732721edf7c32d883ffefa52d6e43339c6ee328c88c3cb5f0d87f6760347b599L91-R95) [[3]](diffhunk://#diff-732721edf7c32d883ffefa52d6e43339c6ee328c88c3cb5f0d87f6760347b599L103-R115)

Enhancements to `DrawerFooter` component:

* [`frontend/webapp/containers/main/overview/overview-drawer/drawer-footer/index.tsx`](diffhunk://#diff-99d52f506bacae9503bbf9eec5f6f3411a0b7e9435a0df40137dd39b545c43e7L1-R66): Refactored the `DrawerFooter` component to use transitions and accept customizable button labels.

Styling adjustments:

* [`frontend/webapp/reuseable-components/modal/warning-modal/index.tsx`](diffhunk://#diff-4cf705009c80d686e304976cb245e4804070372e8e9e8ecc2a97e2a0ee93194fL31-R32): Adjusted the padding of the `Content` component based on the presence of a note. [[1]](diffhunk://#diff-4cf705009c80d686e304976cb245e4804070372e8e9e8ecc2a97e2a0ee93194fL31-R32) [[2]](diffhunk://#diff-4cf705009c80d686e304976cb245e4804070372e8e9e8ecc2a97e2a0ee93194fL73-R73)
  • Loading branch information
BenElferink authored Dec 1, 2024
1 parent fa73020 commit f5020e0
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 109 deletions.
27 changes: 17 additions & 10 deletions frontend/webapp/components/modals/delete-warning/index.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
import React from 'react';
import { OVERVIEW_ENTITY_TYPES } from '@/types';
import { WarningModal } from '@/reuseable-components';
import { NotificationType } from '@/types';

interface Props {
isOpen: boolean;
noOverlay?: boolean;
name?: string;
note?: {
type: NotificationType;
title: string;
message: string;
};
type?: OVERVIEW_ENTITY_TYPES;
isLastItem?: boolean;
onApprove: () => void;
onDeny: () => void;
}

const DeleteWarning: React.FC<Props> = ({ isOpen, noOverlay, name, note, onApprove, onDeny }) => {
const DeleteWarning: React.FC<Props> = ({ isOpen, noOverlay, name, type, isLastItem, onApprove, onDeny }) => {
const actionText = type === OVERVIEW_ENTITY_TYPES.SOURCE ? 'uninstrument' : 'delete';

return (
<WarningModal
isOpen={isOpen}
noOverlay={noOverlay}
title={`Delete${name ? ` ${name}` : ''}`}
description='Are you sure you want to delete?'
note={note}
title={`${actionText.charAt(0).toUpperCase() + actionText.substring(1)}${name ? ` ${name}` : ''}`}
description={`Are you sure you want to ${actionText}?`}
note={
isLastItem
? {
type: 'warning',
title: `You're about to ${actionText} the last ${type}`,
message: 'This will break your pipeline!',
}
: undefined
}
approveButton={{
text: 'Confirm',
variant: 'danger',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React, { useState } from 'react';
import Image from 'next/image';
import styled from 'styled-components';
import { IAppState, useAppStore } from '@/store';
import type { ConfiguredDestination } from '@/types';
import { ConfiguredFields, DeleteWarning } from '@/components';
import { Button, Divider, ExtendIcon, Text } from '@/reuseable-components';
import { OVERVIEW_ENTITY_TYPES, type ConfiguredDestination } from '@/types';

const Container = styled.div`
display: flex;
Expand Down Expand Up @@ -144,15 +144,8 @@ const ConfiguredDestinationsListItem: React.FC<{ item: ConfiguredDestination; is
<DeleteWarning
isOpen={deleteWarning}
name={item.displayName || item.type}
note={
isLastItem
? {
type: 'warning',
title: "You're about to delete the last destination",
message: 'This will break your pipeline!',
}
: undefined
}
type={OVERVIEW_ENTITY_TYPES.DESTINATION}
isLastItem={isLastItem}
onApprove={() => removeConfiguredDestination(item)}
onDeny={() => setDeleteWarning(false)}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useMemo, useState } from 'react';
import Image from 'next/image';
import { slide } from '@/styles';
import theme from '@/styles/theme';
import { useAppStore } from '@/store';
import styled from 'styled-components';
import { DeleteWarning } from '@/components';
import { OVERVIEW_ENTITY_TYPES } from '@/types';
import { useSourceCRUD, useTransition } from '@/hooks';
import { Badge, Button, Divider, Text } from '@/reuseable-components';

Expand Down Expand Up @@ -68,34 +70,18 @@ const MultiSourceControl = () => {
</Button>

<Button variant='tertiary' onClick={() => setIsWarnModalOpen(true)}>
<Image src='/icons/common/circled-cross.svg' alt='' width={20} height={20} />
<Text family='secondary' decoration='underline'>
Uninstrument
</Text>
</Button>

{/* exists in FIGMA, but has same functionality - exclude until we change instrumented behaviour */}

{/* <Button variant='tertiary' onClick={() => setIsWarnModalOpen(true)}>
<Image src='/icons/common/trash.svg' alt='' width={16} height={16} />
<Text family='secondary' decoration='underline' color={theme.text.error}>
Remove
Uninstrument
</Text>
</Button> */}
</Button>
</Transition>

<DeleteWarning
isOpen={isWarnModalOpen}
name={`${totalSelected} sources`}
note={
totalSelected === sources.length
? {
type: 'warning',
title: "You're about to delete the last source",
message: 'This will break your pipeline!',
}
: undefined
}
type={OVERVIEW_ENTITY_TYPES.SOURCE}
isLastItem={totalSelected === sources.length}
onApprove={onDelete}
onDeny={() => setIsWarnModalOpen(false)}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,75 +1,66 @@
// DrawerFooter.tsx
import React, { useEffect, useState } from 'react';
import React from 'react';
import Image from 'next/image';
import styled, { css } from 'styled-components';
import { slide } from '@/styles';
import theme from '@/styles/theme';
import styled from 'styled-components';
import { useTransition } from '@/hooks';
import { Button, Text } from '@/reuseable-components';

interface DrawerFooterProps {
interface Props {
isOpen: boolean;
onSave: () => void;
saveLabel?: string;
onCancel: () => void;
cancelLabel?: string;
onDelete: () => void;
deleteLabel?: string;
}

const DrawerFooter: React.FC<DrawerFooterProps> = ({ onSave, onCancel, onDelete }) => {
const [isVisible, setIsVisible] = useState(false);

useEffect(() => {
// Trigger animation on mount
setIsVisible(true);
}, []);

return (
<FooterContainer $isVisible={isVisible}>
<LeftButtonsWrapper>
<FooterButton variant='primary' onClick={onSave}>
<ButtonText $variant='primary'>Save</ButtonText>
</FooterButton>
<FooterButton variant='secondary' onClick={onCancel}>
<ButtonText>Cancel</ButtonText>
</FooterButton>
</LeftButtonsWrapper>
<FooterButton style={{ width: 100 }} variant='tertiary' onClick={onDelete}>
<Image src='/icons/common/trash.svg' alt='Delete' width={16} height={16} />
<ButtonText $variant='tertiary'>Delete</ButtonText>
</FooterButton>
</FooterContainer>
);
};

export default DrawerFooter;

const FooterContainer = styled.div<{ $isVisible: boolean }>`
display: flex;
justify-content: space-between;
gap: 8px;
padding: 24px 18px 24px 32px;
border-top: 1px solid ${({ theme }) => theme.colors.border};
background-color: ${({ theme }) => theme.colors.translucent_bg};
border-top: 1px solid rgba(249, 249, 249, 0.24);
opacity: 0;
transform: translateY(20px);
transition: opacity 0.3s ease, transform 0.3s ease;
${({ $isVisible }) =>
$isVisible &&
css`
opacity: 1;
transform: translateY(0);
`}
transform: translateY(100%);
`;

const LeftButtonsWrapper = styled.div`
display: flex;
gap: 8px;
const AlignRight = styled.div`
margin-left: auto;
`;

const FooterButton = styled(Button)`
width: 140px;
`;

const ButtonText = styled(Text)<{ $variant?: 'primary' | 'secondary' | 'tertiary' }>`
color: ${({ theme, $variant }) => ($variant === 'primary' ? theme.text.primary : $variant === 'tertiary' ? theme.text.error : theme.text.secondary)};
font-size: 14px;
font-weight: 600;
font-family: ${({ theme }) => theme.font_family.secondary};
text-transform: uppercase;
width: fit-content;
`;

const DrawerFooter: React.FC<Props> = ({ isOpen, onSave, saveLabel = 'Save', onCancel, cancelLabel = 'Cancel', onDelete, deleteLabel = 'Delete' }) => {
const Transition = useTransition({
container: FooterContainer,
animateIn: slide.in['bottom'],
animateOut: slide.out['bottom'],
});

return (
<Transition enter={isOpen}>
<FooterButton variant='primary' onClick={onSave}>
{saveLabel}
</FooterButton>
<FooterButton variant='secondary' onClick={onCancel}>
{cancelLabel}
</FooterButton>

<AlignRight>
<FooterButton variant='tertiary' onClick={onDelete}>
<Image src='/icons/common/trash.svg' alt='Delete' width={16} height={16} />
<Text color={theme.text.error} size={14} family='secondary'>
{deleteLabel}
</Text>
</FooterButton>
</AlignRight>
</Transition>
);
};

export default DrawerFooter;
20 changes: 8 additions & 12 deletions frontend/webapp/containers/main/overview/overview-drawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ const OverviewDrawer: React.FC<Props & PropsWithChildren> = ({ children, title,

const titleRef = useRef<DrawerHeaderRef>(null);

const isSource = selectedItem?.type === OVERVIEW_ENTITY_TYPES.SOURCE;
const isDestination = selectedItem?.type === OVERVIEW_ENTITY_TYPES.DESTINATION;

const closeDrawer = () => {
setSelectedItem(null);
onEdit(false);
Expand Down Expand Up @@ -88,8 +91,8 @@ const OverviewDrawer: React.FC<Props & PropsWithChildren> = ({ children, title,
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;
if (isSource) isLast = sources.length === 1;
if (isDestination) isLast = destinations.length === 1;

return isLast;
};
Expand All @@ -100,23 +103,16 @@ const OverviewDrawer: React.FC<Props & PropsWithChildren> = ({ children, title,
<DrawerContent>
<DrawerHeader ref={titleRef} title={title} titleTooltip={titleTooltip} imageUri={imageUri} isEdit={isEdit} onEdit={() => onEdit(true)} onClose={isEdit ? clickCancel : closeDrawer} />
<ContentArea>{children}</ContentArea>
{isEdit && <DrawerFooter onSave={clickSave} onCancel={clickCancel} onDelete={clickDelete} />}
<DrawerFooter isOpen={isEdit} onSave={clickSave} onCancel={clickCancel} onDelete={clickDelete} deleteLabel={isSource ? 'Uninstrument' : undefined} />
</DrawerContent>
</Drawer>

<DeleteWarning
isOpen={isDeleteModalOpen}
noOverlay
name={`${selectedItem?.type}${title ? ` (${title})` : ''}`}
note={
isLastItem()
? {
type: 'warning',
title: `You're about to delete the last ${selectedItem?.type}`,
message: 'This will break your pipeline!',
}
: undefined
}
type={selectedItem?.type}
isLastItem={isLastItem()}
onApprove={handleDelete}
onDeny={closeWarningModals}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ const Container = styled.div`
padding: 24px 32px;
`;

const Content = styled.div`
padding: 12px 0px 32px 0;
const Content = styled.div<{ $withNote: boolean }>`
padding: ${({ $withNote }) => ($withNote ? '12px 0px' : '12px 0px 32px 0')};
`;

const Title = styled(Text)`
Expand Down Expand Up @@ -70,7 +70,7 @@ export const WarningModal: React.FC<Props> = ({ isOpen, noOverlay, title = '', d
<Container>
<Title>{title}</Title>

<Content>
<Content $withNote={!!note}>
<Description>{description}</Description>
</Content>

Expand Down

0 comments on commit f5020e0

Please sign in to comment.