From bfb038c725d368d1f0027e9bcd2c96e3837c2706 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Mon, 23 Jan 2023 10:44:25 +0100 Subject: [PATCH] feat: pulsing avatar for import (#2961) --- .../project/Project/Import/FileDropZone.tsx | 11 +++-- .../Project/Import/ImportExplanation.tsx | 47 +++++++++++++++++++ .../project/Project/Import/ImportModal.tsx | 28 +++++++---- .../project/Project/Import/PulsingAvatar.tsx | 21 +++++++++ .../Project/Import/StyledFileDropZone.tsx | 2 +- 5 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 frontend/src/component/project/Project/Import/ImportExplanation.tsx create mode 100644 frontend/src/component/project/Project/Import/PulsingAvatar.tsx diff --git a/frontend/src/component/project/Project/Import/FileDropZone.tsx b/frontend/src/component/project/Project/Import/FileDropZone.tsx index 8edcc798c1..7d452a8617 100644 --- a/frontend/src/component/project/Project/Import/FileDropZone.tsx +++ b/frontend/src/component/project/Project/Import/FileDropZone.tsx @@ -1,4 +1,4 @@ -import React, { FC, useCallback } from 'react'; +import React, { FC, useCallback, useEffect } from 'react'; import { useDropzone } from 'react-dropzone'; import { Box } from '@mui/material'; @@ -7,10 +7,11 @@ const formatJSON = (json: string) => JSON.stringify(JSON.parse(json), null, 4); interface IFileDropZoneProps { onSuccess: (message: string) => void; onError: (error: string) => void; + onDragStatusChange: (dragOn: boolean) => void; } const onFileDropped = - ({ onSuccess, onError }: IFileDropZoneProps) => + ({ onSuccess, onError }: Omit) => (e: ProgressEvent) => { const contents = e?.target?.result; if (typeof contents === 'string') { @@ -30,6 +31,7 @@ export const FileDropZone: FC = ({ onSuccess, onError, children, + onDragStatusChange, ...props }) => { const onDrop = useCallback(([file]) => { @@ -37,13 +39,16 @@ export const FileDropZone: FC = ({ reader.onload = onFileDropped({ onSuccess, onError }); reader.readAsText(file); }, []); - const { getRootProps, getInputProps } = useDropzone({ + const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: { 'application/json': ['.json'], }, maxFiles: 1, }); + useEffect(() => { + onDragStatusChange(isDragActive); + }, [isDragActive]); return ( diff --git a/frontend/src/component/project/Project/Import/ImportExplanation.tsx b/frontend/src/component/project/Project/Import/ImportExplanation.tsx new file mode 100644 index 0000000000..b70b6cf7e9 --- /dev/null +++ b/frontend/src/component/project/Project/Import/ImportExplanation.tsx @@ -0,0 +1,47 @@ +import React, { FC } from 'react'; +import { Box, styled, Typography } from '@mui/material'; + +const ImportExplanationContainer = styled(Box)(({ theme }) => ({ + backgroundColor: theme.palette.secondaryContainer, + borderRadius: theme.shape.borderRadiusLarge, + padding: theme.spacing(3), +})); + +const ImportExplanationHeader = styled(Typography)(({ theme }) => ({ + marginBottom: theme.spacing(0.5), +})); + +const ImportExplanationDescription = styled(Typography)(({ theme }) => ({ + marginBottom: theme.spacing(3), + color: theme.palette.text.secondary, + fontSize: theme.fontSizes.smallBody, +})); + +export const ImportExplanation: FC = () => ( + + + What is being imported? + + + Feature toggles will be imported with full configuration: +
    +
  • strategies
  • +
  • context fields
  • +
  • variants
  • +
  • tags
  • +
  • feature toggle status
  • +
+
+ Exceptions? + + If the feature toggle already exists in the new instance, it will be + overwritten + + What is not imported? + + If we detect segments or custom strategies in your imported file, we + will stop the import. You need to create them first in the new + instance and run the import again + +
+); diff --git a/frontend/src/component/project/Project/Import/ImportModal.tsx b/frontend/src/component/project/Project/Import/ImportModal.tsx index 2a200ab85a..615a9bc8f9 100644 --- a/frontend/src/component/project/Project/Import/ImportModal.tsx +++ b/frontend/src/component/project/Project/Import/ImportModal.tsx @@ -6,7 +6,6 @@ import { TextField, Box, Typography, - Avatar, } from '@mui/material'; import { SidebarModal } from 'component/common/SidebarModal/SidebarModal'; import { ArrowUpward } from '@mui/icons-material'; @@ -16,11 +15,13 @@ import { StyledFileDropZone } from './StyledFileDropZone'; import { ConditionallyRender } from '../../../common/ConditionallyRender/ConditionallyRender'; import useToast from 'hooks/useToast'; import { ImportOptions } from './ImportOptions'; +import { ImportExplanation } from './ImportExplanation'; +import { PulsingAvatar } from './PulsingAvatar'; const LayoutContainer = styled('div')(({ theme }) => ({ backgroundColor: '#fff', - height: '100vh', - padding: theme.spacing(4, 8, 4, 8), + minHeight: '100vh', + padding: theme.spacing(3, 8, 3, 8), display: 'flex', flexDirection: 'column', gap: theme.spacing(3), @@ -42,7 +43,7 @@ const SelectFileMessage = styled(Typography)(({ theme }) => ({ })); const MaxSizeMessage = styled(Typography)(({ theme }) => ({ - marginTop: theme.spacing(9), + marginTop: theme.spacing(4), color: theme.palette.text.secondary, })); @@ -50,7 +51,7 @@ const ActionsContainer = styled(Box)(({ theme }) => ({ width: '100%', borderTop: `1px solid ${theme.palette.dividerAlternative}`, marginTop: 'auto', - paddingTop: theme.spacing(4), + paddingTop: theme.spacing(3), display: 'flex', justifyContent: 'flex-end', })); @@ -70,6 +71,7 @@ export const ImportModal = ({ open, setOpen, project }: IImportModalProps) => { const [environment, setEnvironment] = useState(''); const [importPayload, setImportPayload] = useState(''); const [activeTab, setActiveTab] = useState('file'); + const [dragActive, setDragActive] = useState(false); const onSubmit = async () => { await createImport({ @@ -132,11 +134,16 @@ export const ImportModal = ({ open, setOpen, project }: IImportModalProps) => { title: error, }); }} + onDragStatusChange={setDragActive} > - + - - Drop your file here + + + {dragActive + ? 'Drop your file to upload' + : 'Drop your file here'} + or select a file from your device @@ -155,11 +162,12 @@ export const ImportModal = ({ open, setOpen, project }: IImportModalProps) => { } value={importPayload} multiline - minRows={17} - maxRows={17} + minRows={13} + maxRows={13} /> } /> +