mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	fix: misc UI/UX fixes, mostly related with favorites (#2683)
https://linear.app/unleash/issue/2-504/misc-frontend-related-fixes-mostly-related-with-favorites
This commit is contained in:
		
							parent
							
								
									a8cd3166d1
								
							
						
					
					
						commit
						e05d924663
					
				@ -1,11 +1,5 @@
 | 
			
		||||
import { useEffect, useMemo, useState, VFC } from 'react';
 | 
			
		||||
import {
 | 
			
		||||
    IconButton,
 | 
			
		||||
    styled,
 | 
			
		||||
    Tooltip,
 | 
			
		||||
    useMediaQuery,
 | 
			
		||||
    useTheme,
 | 
			
		||||
} from '@mui/material';
 | 
			
		||||
import { IconButton, Tooltip, useMediaQuery, useTheme } from '@mui/material';
 | 
			
		||||
import { useSearchParams, Link } from 'react-router-dom';
 | 
			
		||||
import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table';
 | 
			
		||||
import { TablePlaceholder, VirtualizedTable } from 'component/common/Table';
 | 
			
		||||
@ -41,14 +35,6 @@ import {
 | 
			
		||||
    UG_REMOVE_USER_BTN_ID,
 | 
			
		||||
} from 'utils/testIds';
 | 
			
		||||
 | 
			
		||||
const StyledEdit = styled(Edit)(({ theme }) => ({
 | 
			
		||||
    fontSize: theme.fontSizes.mainHeader,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledDelete = styled(Delete)(({ theme }) => ({
 | 
			
		||||
    fontSize: theme.fontSizes.mainHeader,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const groupUsersPlaceholder: IGroupUser[] = Array(15).fill({
 | 
			
		||||
    name: 'Name of the user',
 | 
			
		||||
    username: 'Username of the user',
 | 
			
		||||
@ -248,7 +234,7 @@ export const Group: VFC = () => {
 | 
			
		||||
                                        title: 'Edit group',
 | 
			
		||||
                                    }}
 | 
			
		||||
                                >
 | 
			
		||||
                                    <StyledEdit />
 | 
			
		||||
                                    <Edit />
 | 
			
		||||
                                </PermissionIconButton>
 | 
			
		||||
                                <PermissionIconButton
 | 
			
		||||
                                    data-testid={UG_DELETE_BTN_ID}
 | 
			
		||||
@ -259,7 +245,7 @@ export const Group: VFC = () => {
 | 
			
		||||
                                        title: 'Delete group',
 | 
			
		||||
                                    }}
 | 
			
		||||
                                >
 | 
			
		||||
                                    <StyledDelete />
 | 
			
		||||
                                    <Delete />
 | 
			
		||||
                                </PermissionIconButton>
 | 
			
		||||
                            </>
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import React, { VFC } from 'react';
 | 
			
		||||
import { IconButton, SxProps, Theme } from '@mui/material';
 | 
			
		||||
import { VFC } from 'react';
 | 
			
		||||
import { IconButton, IconButtonProps } from '@mui/material';
 | 
			
		||||
import { ConditionallyRender } from '../ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import {
 | 
			
		||||
    Star as StarIcon,
 | 
			
		||||
@ -7,30 +7,24 @@ import {
 | 
			
		||||
} from '@mui/icons-material';
 | 
			
		||||
import { TooltipResolver } from '../TooltipResolver/TooltipResolver';
 | 
			
		||||
 | 
			
		||||
interface IFavoriteIconButtonProps {
 | 
			
		||||
    onClick: (event?: any) => void;
 | 
			
		||||
interface IFavoriteIconButtonProps extends IconButtonProps {
 | 
			
		||||
    isFavorite: boolean;
 | 
			
		||||
    size?: 'medium' | 'large';
 | 
			
		||||
    sx?: SxProps<Theme>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const FavoriteIconButton: VFC<IFavoriteIconButtonProps> = ({
 | 
			
		||||
    onClick,
 | 
			
		||||
    isFavorite,
 | 
			
		||||
    size = 'large',
 | 
			
		||||
    sx,
 | 
			
		||||
    ...props
 | 
			
		||||
}) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <IconButton
 | 
			
		||||
            size={size}
 | 
			
		||||
            data-loading
 | 
			
		||||
            sx={{ mr: 1, ...sx }}
 | 
			
		||||
            onClick={onClick}
 | 
			
		||||
        <TooltipResolver
 | 
			
		||||
            title={isFavorite ? 'Remove from favorites' : 'Add to favorites'}
 | 
			
		||||
        >
 | 
			
		||||
            <ConditionallyRender
 | 
			
		||||
                condition={isFavorite}
 | 
			
		||||
                show={
 | 
			
		||||
                    <TooltipResolver title={'Remove from favorites'}>
 | 
			
		||||
            <IconButton size={size} data-loading {...props}>
 | 
			
		||||
                <ConditionallyRender
 | 
			
		||||
                    condition={isFavorite}
 | 
			
		||||
                    show={
 | 
			
		||||
                        <StarIcon
 | 
			
		||||
                            color="primary"
 | 
			
		||||
                            sx={{
 | 
			
		||||
@ -40,10 +34,8 @@ export const FavoriteIconButton: VFC<IFavoriteIconButtonProps> = ({
 | 
			
		||||
                                        : theme.spacing(3),
 | 
			
		||||
                            }}
 | 
			
		||||
                        />
 | 
			
		||||
                    </TooltipResolver>
 | 
			
		||||
                }
 | 
			
		||||
                elseShow={
 | 
			
		||||
                    <TooltipResolver title={'Add to favorites'}>
 | 
			
		||||
                    }
 | 
			
		||||
                    elseShow={
 | 
			
		||||
                        <StarBorderIcon
 | 
			
		||||
                            sx={{
 | 
			
		||||
                                fontSize: theme =>
 | 
			
		||||
@ -52,9 +44,9 @@ export const FavoriteIconButton: VFC<IFavoriteIconButtonProps> = ({
 | 
			
		||||
                                        : theme.spacing(3),
 | 
			
		||||
                            }}
 | 
			
		||||
                        />
 | 
			
		||||
                    </TooltipResolver>
 | 
			
		||||
                }
 | 
			
		||||
            />
 | 
			
		||||
        </IconButton>
 | 
			
		||||
                    }
 | 
			
		||||
                />
 | 
			
		||||
            </IconButton>
 | 
			
		||||
        </TooltipResolver>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@ const StyledMainHeader = styled(Paper)(({ theme }) => ({
 | 
			
		||||
 | 
			
		||||
const StyledTitleHeader = styled('div')(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'flex-start',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    justifyContent: 'space-between',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,11 @@ export const useStyles = makeStyles()(() => ({
 | 
			
		||||
    row: {
 | 
			
		||||
        position: 'absolute',
 | 
			
		||||
        width: '100%',
 | 
			
		||||
        '&:hover': {
 | 
			
		||||
            '.show-row-hover': {
 | 
			
		||||
                display: 'inherit',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    cell: {
 | 
			
		||||
        alignItems: 'center',
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ import {
 | 
			
		||||
    StarBorder as StarBorderIcon,
 | 
			
		||||
} from '@mui/icons-material';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import { TooltipResolver } from '../../../TooltipResolver/TooltipResolver';
 | 
			
		||||
import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver';
 | 
			
		||||
 | 
			
		||||
interface IFavoriteIconCellProps {
 | 
			
		||||
    value?: boolean;
 | 
			
		||||
@ -13,17 +13,15 @@ interface IFavoriteIconCellProps {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const InactiveIconButton = styled(IconButton)(({ theme }) => ({
 | 
			
		||||
    color: 'transparent',
 | 
			
		||||
    '&:hover, &:focus': {
 | 
			
		||||
        color: theme.palette.primary.main,
 | 
			
		||||
    },
 | 
			
		||||
    color: theme.palette.primary.main,
 | 
			
		||||
    display: 'none',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const FavoriteIconCell: VFC<IFavoriteIconCellProps> = ({
 | 
			
		||||
    value = false,
 | 
			
		||||
    onClick,
 | 
			
		||||
}) => (
 | 
			
		||||
    <Box sx={{ pl: 1.25 }}>
 | 
			
		||||
    <Box sx={{ pl: 1.25, display: 'inline-flex' }}>
 | 
			
		||||
        <ConditionallyRender
 | 
			
		||||
            condition={value}
 | 
			
		||||
            show={
 | 
			
		||||
@ -41,6 +39,7 @@ export const FavoriteIconCell: VFC<IFavoriteIconCellProps> = ({
 | 
			
		||||
            elseShow={
 | 
			
		||||
                <TooltipResolver title={'Add to favorites'}>
 | 
			
		||||
                    <InactiveIconButton
 | 
			
		||||
                        className="show-row-hover"
 | 
			
		||||
                        onClick={onClick}
 | 
			
		||||
                        size="small"
 | 
			
		||||
                        sx={{ padding: 1.25 }}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import { Tab, Tabs, useMediaQuery } from '@mui/material';
 | 
			
		||||
import React, { useState } from 'react';
 | 
			
		||||
import { useState } from 'react';
 | 
			
		||||
import { Archive, FileCopy, Label, WatchLater } from '@mui/icons-material';
 | 
			
		||||
import {
 | 
			
		||||
    Link,
 | 
			
		||||
@ -123,7 +123,6 @@ export const FeatureView = () => {
 | 
			
		||||
                                            <FavoriteIconButton
 | 
			
		||||
                                                onClick={onFavorite}
 | 
			
		||||
                                                isFavorite={feature?.favorite}
 | 
			
		||||
                                                sx={{ pr: 0.25 }}
 | 
			
		||||
                                            />
 | 
			
		||||
                                        )}
 | 
			
		||||
                                    />
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,6 @@ export const useStyles = makeStyles()(theme => ({
 | 
			
		||||
        width: '100%',
 | 
			
		||||
        fontSize: theme.fontSizes.mainHeader,
 | 
			
		||||
        fontWeight: 'bold',
 | 
			
		||||
        marginBottom: '0.5rem',
 | 
			
		||||
        display: 'flex',
 | 
			
		||||
        justifyContent: 'space-between',
 | 
			
		||||
        alignItems: 'center',
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ import { styled, Tab, Tabs } from '@mui/material';
 | 
			
		||||
import { Delete, Edit } from '@mui/icons-material';
 | 
			
		||||
import useToast from 'hooks/useToast';
 | 
			
		||||
import useQueryParams from 'hooks/useQueryParams';
 | 
			
		||||
import React, { useEffect, useMemo, useState } from 'react';
 | 
			
		||||
import { useEffect, useMemo, useState } from 'react';
 | 
			
		||||
import ProjectEnvironment from '../ProjectEnvironment/ProjectEnvironment';
 | 
			
		||||
import { ProjectFeaturesArchive } from './ProjectFeaturesArchive/ProjectFeaturesArchive';
 | 
			
		||||
import ProjectOverview from './ProjectOverview';
 | 
			
		||||
@ -28,18 +28,18 @@ import { MainLayout } from 'component/layout/MainLayout/MainLayout';
 | 
			
		||||
import { ProjectChangeRequests } from '../../changeRequest/ProjectChangeRequests/ProjectChangeRequests';
 | 
			
		||||
import { ProjectSettings } from './ProjectSettings/ProjectSettings';
 | 
			
		||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
 | 
			
		||||
import { FavoriteIconButton } from '../../common/FavoriteIconButton/FavoriteIconButton';
 | 
			
		||||
import { useFavoriteProjectsApi } from '../../../hooks/api/actions/useFavoriteProjectsApi/useFavoriteProjectsApi';
 | 
			
		||||
import { FavoriteIconButton } from 'component/common/FavoriteIconButton/FavoriteIconButton';
 | 
			
		||||
import { useFavoriteProjectsApi } from 'hooks/api/actions/useFavoriteProjectsApi/useFavoriteProjectsApi';
 | 
			
		||||
 | 
			
		||||
const StyledDiv = styled('div')(() => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const Row = styled('div')(({ theme }) => ({
 | 
			
		||||
const StyledTopRow = styled('div')(() => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'row',
 | 
			
		||||
    justifyContent: 'center',
 | 
			
		||||
    paddingBottom: theme.spacing(0.25),
 | 
			
		||||
    justifyContent: 'space-between',
 | 
			
		||||
    width: '100%',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const Column = styled('div')(() => ({
 | 
			
		||||
@ -47,11 +47,10 @@ const Column = styled('div')(() => ({
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledName = styled('div')(({ theme }) => ({
 | 
			
		||||
const StyledName = styled('div')(() => ({
 | 
			
		||||
    overflow: 'hidden',
 | 
			
		||||
    textOverflow: 'ellipsis',
 | 
			
		||||
    whiteSpace: 'nowrap',
 | 
			
		||||
    paddingTop: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledTitle = styled('span')(({ theme }) => ({
 | 
			
		||||
@ -62,6 +61,10 @@ const StyledText = styled(StyledTitle)(({ theme }) => ({
 | 
			
		||||
    color: theme.palette.grey[800],
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledFavoriteIconButton = styled(FavoriteIconButton)(({ theme }) => ({
 | 
			
		||||
    marginLeft: theme.spacing(-1.5),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const Project = () => {
 | 
			
		||||
    const projectId = useRequiredPathParam('projectId');
 | 
			
		||||
    const params = useQueryParams();
 | 
			
		||||
@ -158,21 +161,54 @@ const Project = () => {
 | 
			
		||||
        >
 | 
			
		||||
            <div className={styles.header}>
 | 
			
		||||
                <div className={styles.innerContainer}>
 | 
			
		||||
                    <Row>
 | 
			
		||||
                        <ConditionallyRender
 | 
			
		||||
                            condition={Boolean(uiConfig?.flags?.favorites)}
 | 
			
		||||
                            show={() => (
 | 
			
		||||
                                <FavoriteIconButton
 | 
			
		||||
                                    onClick={onFavorite}
 | 
			
		||||
                                    isFavorite={project?.favorite}
 | 
			
		||||
                                    sx={{ pl: 0, pr: 0.25 }}
 | 
			
		||||
                                />
 | 
			
		||||
                            )}
 | 
			
		||||
                        />
 | 
			
		||||
                        <h2 className={styles.title}>
 | 
			
		||||
                            <StyledName data-loading>{projectName}</StyledName>
 | 
			
		||||
                        </h2>
 | 
			
		||||
                    </Row>
 | 
			
		||||
                    <StyledTopRow>
 | 
			
		||||
                        <StyledDiv>
 | 
			
		||||
                            <ConditionallyRender
 | 
			
		||||
                                condition={Boolean(uiConfig?.flags?.favorites)}
 | 
			
		||||
                                show={() => (
 | 
			
		||||
                                    <StyledFavoriteIconButton
 | 
			
		||||
                                        onClick={onFavorite}
 | 
			
		||||
                                        isFavorite={project?.favorite}
 | 
			
		||||
                                    />
 | 
			
		||||
                                )}
 | 
			
		||||
                            />
 | 
			
		||||
                            <h2 className={styles.title}>
 | 
			
		||||
                                <StyledName data-loading>
 | 
			
		||||
                                    {projectName}
 | 
			
		||||
                                </StyledName>
 | 
			
		||||
                            </h2>
 | 
			
		||||
                        </StyledDiv>
 | 
			
		||||
                        <StyledDiv>
 | 
			
		||||
                            <PermissionIconButton
 | 
			
		||||
                                permission={UPDATE_PROJECT}
 | 
			
		||||
                                projectId={projectId}
 | 
			
		||||
                                sx={{
 | 
			
		||||
                                    visibility: isOss() ? 'hidden' : 'visible',
 | 
			
		||||
                                }}
 | 
			
		||||
                                onClick={() =>
 | 
			
		||||
                                    navigate(`/projects/${projectId}/edit`)
 | 
			
		||||
                                }
 | 
			
		||||
                                tooltipProps={{ title: 'Edit project' }}
 | 
			
		||||
                                data-loading
 | 
			
		||||
                            >
 | 
			
		||||
                                <Edit />
 | 
			
		||||
                            </PermissionIconButton>
 | 
			
		||||
                            <PermissionIconButton
 | 
			
		||||
                                permission={DELETE_PROJECT}
 | 
			
		||||
                                projectId={projectId}
 | 
			
		||||
                                sx={{
 | 
			
		||||
                                    visibility: isOss() ? 'hidden' : 'visible',
 | 
			
		||||
                                }}
 | 
			
		||||
                                onClick={() => {
 | 
			
		||||
                                    setShowDelDialog(true);
 | 
			
		||||
                                }}
 | 
			
		||||
                                tooltipProps={{ title: 'Delete project' }}
 | 
			
		||||
                                data-loading
 | 
			
		||||
                            >
 | 
			
		||||
                                <Delete />
 | 
			
		||||
                            </PermissionIconButton>
 | 
			
		||||
                        </StyledDiv>
 | 
			
		||||
                    </StyledTopRow>
 | 
			
		||||
                    <Column>
 | 
			
		||||
                        <h2 className={styles.title}>
 | 
			
		||||
                            <div>
 | 
			
		||||
@ -198,40 +234,6 @@ const Project = () => {
 | 
			
		||||
                                    </StyledText>
 | 
			
		||||
                                </StyledDiv>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <StyledDiv>
 | 
			
		||||
                                <PermissionIconButton
 | 
			
		||||
                                    permission={UPDATE_PROJECT}
 | 
			
		||||
                                    projectId={projectId}
 | 
			
		||||
                                    sx={{
 | 
			
		||||
                                        visibility: isOss()
 | 
			
		||||
                                            ? 'hidden'
 | 
			
		||||
                                            : 'visible',
 | 
			
		||||
                                    }}
 | 
			
		||||
                                    onClick={() =>
 | 
			
		||||
                                        navigate(`/projects/${projectId}/edit`)
 | 
			
		||||
                                    }
 | 
			
		||||
                                    tooltipProps={{ title: 'Edit project' }}
 | 
			
		||||
                                    data-loading
 | 
			
		||||
                                >
 | 
			
		||||
                                    <Edit />
 | 
			
		||||
                                </PermissionIconButton>
 | 
			
		||||
                                <PermissionIconButton
 | 
			
		||||
                                    permission={DELETE_PROJECT}
 | 
			
		||||
                                    projectId={projectId}
 | 
			
		||||
                                    sx={{
 | 
			
		||||
                                        visibility: isOss()
 | 
			
		||||
                                            ? 'hidden'
 | 
			
		||||
                                            : 'visible',
 | 
			
		||||
                                    }}
 | 
			
		||||
                                    onClick={() => {
 | 
			
		||||
                                        setShowDelDialog(true);
 | 
			
		||||
                                    }}
 | 
			
		||||
                                    tooltipProps={{ title: 'Delete project' }}
 | 
			
		||||
                                    data-loading
 | 
			
		||||
                                >
 | 
			
		||||
                                    <Delete />
 | 
			
		||||
                                </PermissionIconButton>
 | 
			
		||||
                            </StyledDiv>
 | 
			
		||||
                        </h2>
 | 
			
		||||
                    </Column>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
@ -56,7 +56,7 @@ export const ProjectCard = ({
 | 
			
		||||
    const canDeleteProject =
 | 
			
		||||
        hasAccess(DELETE_PROJECT, id) && id !== DEFAULT_PROJECT_ID;
 | 
			
		||||
 | 
			
		||||
    const onFavorite = async (e: Event) => {
 | 
			
		||||
    const onFavorite = async (e: React.SyntheticEvent) => {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
        if (isFavorite) {
 | 
			
		||||
            await unfavorite(id);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user