1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

Fix: UI improvements (#1114)

* fix: segments table author column width

* fix: update feature form ui

* fix: strategies breadcrumbs

* fix: api token page title

* fix: deprecated strategy label color

* fix: project access remove user toast

* fix: addon enable toast message

* fix: ces from ui

* fix: ui improvements with dialog typography

* fix: revert ces

* fix: change password error type
This commit is contained in:
Tymoteusz Czech 2022-06-28 12:58:10 +02:00 committed by GitHub
parent 566d0613a4
commit c0b52fa672
25 changed files with 74 additions and 67 deletions

View File

@ -53,7 +53,7 @@ export const ConfiguredAddons = () => {
type: 'success',
title: 'Success',
text: !addon.enabled
? 'Addon is now active'
? 'Addon is now enabled'
: 'Addon is now disabled',
});
} catch (error: unknown) {

View File

@ -11,6 +11,9 @@ import { ConfirmToken } from '../ConfirmToken/ConfirmToken';
import { useState } from 'react';
import { scrollToTop } from 'component/common/util';
import { formatUnknownError } from 'utils/formatUnknownError';
import { usePageTitle } from 'hooks/usePageTitle';
const pageTitle = 'Create API token';
export const CreateApiToken = () => {
const { setToastApiError } = useToast();
@ -36,6 +39,8 @@ export const CreateApiToken = () => {
const { createToken, loading } = useApiTokensApi();
usePageTitle(pageTitle);
const handleSubmit = async (e: Event) => {
e.preventDefault();
if (!isValid()) {
@ -76,7 +81,7 @@ export const CreateApiToken = () => {
return (
<FormTemplate
loading={loading}
title="Create Api Token"
title={pageTitle}
description="In order to connect to Unleash clients will need an API token to grant access. A client SDK will need to token with 'client privileges', which allows them to fetch feature toggle configuration and post usage metrics back."
documentationLink="https://docs.getunleash.io/reference/api-tokens-and-client-keys"
documentationLinkLabel="API tokens documentation"

View File

@ -10,24 +10,24 @@ import PasswordChecker, {
import { useThemeStyles } from 'themes/themeStyles';
import PasswordMatcher from 'component/user/common/ResetPasswordForm/PasswordMatcher/PasswordMatcher';
import { IUser } from 'interfaces/user';
import useAdminUsersApi from 'hooks/api/actions/useAdminUsersApi/useAdminUsersApi';
interface IChangePasswordProps {
showDialog: boolean;
closeDialog: () => void;
changePassword: (userId: number, password: string) => Promise<Response>;
user: IUser;
}
const ChangePassword = ({
showDialog,
closeDialog,
changePassword,
user,
}: IChangePasswordProps) => {
const [data, setData] = useState<Record<string, string>>({});
const [error, setError] = useState<string>();
const [validPassword, setValidPassword] = useState(false);
const { classes: themeStyles } = useThemeStyles();
const { changePassword } = useAdminUsersApi();
const updateField: React.ChangeEventHandler<HTMLInputElement> = event => {
setError(undefined);

View File

@ -45,8 +45,7 @@ const UsersList = () => {
const navigate = useNavigate();
const { users, roles, refetch, loading } = useUsers();
const { setToastData, setToastApiError } = useToast();
const { removeUser, changePassword, userLoading, userApiErrors } =
useAdminUsersApi();
const { removeUser, userLoading, userApiErrors } = useAdminUsersApi();
const [pwDialog, setPwDialog] = useState<{ open: boolean; user?: IUser }>({
open: false,
});
@ -320,7 +319,6 @@ const UsersList = () => {
<ChangePassword
showDialog={pwDialog.open}
closeDialog={closePwDialog}
changePassword={changePassword}
user={pwDialog.user!}
/>
)}

View File

@ -23,7 +23,6 @@ const BreadcrumbNav = () => {
item !== 'logs' &&
item !== 'metrics' &&
item !== 'copy' &&
item !== 'strategies' &&
item !== 'features' &&
item !== 'features2' &&
item !== 'create-toggle' &&

View File

@ -1,5 +1,5 @@
import useFeatureApi from 'hooks/api/actions/useFeatureApi/useFeatureApi';
import { DialogContentText } from '@mui/material';
import { Typography } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { Dialogue } from 'component/common/Dialogue/Dialogue';
import React from 'react';
@ -25,14 +25,13 @@ export const FeatureStaleDialog = ({
const { patchFeatureToggle } = useFeatureApi();
const toggleToStaleContent = (
<DialogContentText>
Setting a toggle to stale marks it for cleanup
</DialogContentText>
<Typography>Setting a toggle to stale marks it for cleanup</Typography>
);
const toggleToActiveContent = (
<DialogContentText>
<Typography>
Setting a toggle to active marks it as in active use
</DialogContentText>
</Typography>
);
const toggleActionText = isStale ? 'active' : 'stale';

View File

@ -16,7 +16,7 @@ export const useStyles = makeStyles()(theme => ({
display: 'flex',
alignItems: 'center',
backgroundColor: theme.palette.background.paper,
border: `1px solid ${theme.palette.grey[300]}`,
border: `1px solid ${theme.palette.grey[500]}`,
borderRadius: theme.shape.borderRadiusExtraLarge,
padding: '3px 5px 3px 12px',
width: '100%',

View File

@ -76,7 +76,7 @@ const CreateFeature = () => {
return (
<FormTemplate
loading={loading}
title="Create Feature toggle"
title="Create feature toggle"
description="Feature toggles support different use cases, each with their own specific needs such as simple static routing or more complex routing.
The feature toggle is disabled when created and you decide when to enable"
documentationLink="https://docs.getunleash.io/advanced/feature_toggle_types"
@ -102,7 +102,7 @@ const CreateFeature = () => {
clearErrors={clearErrors}
>
<CreateButton
name="Feature"
name="feature toggle"
permission={CREATE_FEATURE}
projectId={project}
data-testid={CF_CREATE_BTN_ID}

View File

@ -33,10 +33,11 @@ export const useStyles = makeStyles()(theme => ({
},
inputDescription: {
marginBottom: '0.5rem',
color: theme.palette.text.secondary,
},
typeDescription: {
fontSize: theme.fontSizes.smallBody,
color: theme.palette.grey[600],
color: theme.palette.text.secondary,
top: '-13px',
position: 'relative',
},

View File

@ -4,7 +4,7 @@ export const useStyles = makeStyles()(theme => ({
title: {
margin: 0,
marginBottom: '.5rem',
fontSize: theme.fontSizes.smallerBody,
fontSize: theme.fontSizes.smallBody,
fontWeight: theme.fontWeight.thin,
color: theme.palette.grey[800],
},

View File

@ -2,8 +2,7 @@ import { FeatureMetricsTable } from '../FeatureMetricsTable/FeatureMetricsTable'
import { IFeatureMetricsRaw } from 'interfaces/featureToggle';
import { FeatureMetricsStatsRaw } from '../FeatureMetricsStats/FeatureMetricsStatsRaw';
import { FeatureMetricsChart } from '../FeatureMetricsChart/FeatureMetricsChart';
import { FeatureMetricsEmpty } from '../FeatureMetricsEmpty/FeatureMetricsEmpty';
import { Box } from '@mui/material';
import { Box, Typography } from '@mui/material';
import theme from 'themes/theme';
import { useId } from 'hooks/useId';
@ -22,7 +21,14 @@ export const FeatureMetricsContent = ({
if (metrics.length === 0) {
return (
<Box mt={6}>
<FeatureMetricsEmpty />
<Typography variant="body1" paragraph>
We have yet to receive any metrics for this feature toggle
in the selected time period.
</Typography>
<Typography variant="body1" paragraph>
Please note that, since the SDKs send metrics on an
interval, it might take some time before metrics appear.
</Typography>
</Box>
);
}

View File

@ -1,16 +0,0 @@
import { Typography } from '@mui/material';
export const FeatureMetricsEmpty = () => {
return (
<>
<Typography variant="body1" paragraph>
We have yet to receive any metrics for this feature toggle in
the selected time period.
</Typography>
<Typography variant="body1" paragraph>
Please note that, since the SDKs send metrics on an interval, it
might take some time before metrics appear.
</Typography>
</>
);
};

View File

@ -1,4 +1,4 @@
import { DialogContentText } from '@mui/material';
import { Typography } from '@mui/material';
import React, { useState } from 'react';
import { Dialogue } from 'component/common/Dialogue/Dialogue';
import Input from 'component/common/Input/Input';
@ -30,7 +30,7 @@ const AddTagDialog = ({ open, setOpen }: IAddTagDialogProps) => {
const { addTagToFeature, loading } = useFeatureApi();
const { refetch } = useTags(featureId);
const [errors, setErrors] = useState({ tagError: '' });
const { setToastData, setToastApiError } = useToast();
const { setToastData } = useToast();
const [tag, setTag] = useState(DEFAULT_TAG);
const onCancel = () => {
@ -64,7 +64,6 @@ const AddTagDialog = ({ open, setOpen }: IAddTagDialogProps) => {
});
} catch (error: unknown) {
const message = formatUnknownError(error);
setToastApiError(message);
setErrors({ tagError: message });
}
};
@ -84,9 +83,9 @@ const AddTagDialog = ({ open, setOpen }: IAddTagDialogProps) => {
formId={formId}
>
<>
<DialogContentText>
<Typography paragraph>
Tags allow you to group features together
</DialogContentText>
</Typography>
<form id={formId} onSubmit={onSubmit}>
<section className={styles.dialogFormContent}>
<TagSelect

View File

@ -27,8 +27,6 @@ export const useStyles = makeStyles()(theme => ({
position: 'absolute',
top: 0,
right: 0,
padding: '1rem',
cursor: 'pointer',
},
closeIcon: {
fontSize: '1.5rem',

View File

@ -1,4 +1,4 @@
import { Modal } from '@mui/material';
import { IconButton, Modal } from '@mui/material';
import React, { useContext } from 'react';
import {
feedbackCESContext,
@ -16,12 +16,6 @@ export const FeedbackCES = ({ state }: IFeedbackCESProps) => {
const { hideFeedbackCES } = useContext(feedbackCESContext);
const { classes: styles } = useStyles();
const closeButton = (
<button className={styles.close} onClick={hideFeedbackCES}>
<CloseOutlined titleAccess="Close" className={styles.closeIcon} />
</button>
);
const modalContent = state && (
<FeedbackCESForm state={state} onClose={hideFeedbackCES} />
);
@ -34,7 +28,14 @@ export const FeedbackCES = ({ state }: IFeedbackCESProps) => {
>
<div className={styles.overlay}>
<div className={styles.modal}>
{closeButton}
<div className={styles.close}>
<IconButton onClick={hideFeedbackCES} size="large">
<CloseOutlined
titleAccess="Close"
className={styles.closeIcon}
/>
</IconButton>
</div>
{modalContent}
</div>
</div>

View File

@ -14,7 +14,7 @@ export const useStyles = makeStyles()(theme => ({
all: 'unset',
display: 'block',
textAlign: 'center',
color: theme.palette.grey[600],
color: theme.palette.text.secondary,
},
subtitle: {
all: 'unset',

View File

@ -8,9 +8,9 @@ export const useStyles = makeStyles()(theme => ({
margin: '0 auto',
},
scoreHelp: {
width: '8rem',
width: '6.25rem',
whiteSpace: 'nowrap',
color: theme.palette.grey[600],
color: theme.palette.text.secondary,
'&:first-of-type': {
textAlign: 'right',
},

View File

@ -7,7 +7,7 @@ exports[`FeedbackCESForm 1`] = `
class="tss-fdcp7c-container"
>
<h1
class="tss-1a5bydb-title"
class="tss-iyd7t0-title"
>
Please help us improve
</h1>
@ -24,7 +24,7 @@ exports[`FeedbackCESForm 1`] = `
class="tss-io6e1g-scoreInput"
>
<span
class="tss-b4a690-scoreHelp"
class="tss-16omcck-scoreHelp"
>
Very difficult
</span>
@ -113,7 +113,7 @@ exports[`FeedbackCESForm 1`] = `
</span>
</label>
<span
class="tss-b4a690-scoreHelp"
class="tss-16omcck-scoreHelp"
>
Very easy
</span>

View File

@ -57,7 +57,9 @@ export const ProjectAccessPage = () => {
refetchProjectAccess();
setToastData({
type: 'success',
title: 'The user has been removed from project',
title: `${
user.email || user.username || 'The user'
} has been removed from project`,
});
} catch (err: any) {
setToastData({

View File

@ -1,3 +1,4 @@
import React, { useContext } from 'react';
import { CreateButton } from 'component/common/CreateButton/CreateButton';
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import { CREATE_SEGMENT } from 'component/providers/AccessProvider/permissions';
@ -6,7 +7,6 @@ import { useConstraintsValidation } from 'hooks/api/getters/useConstraintsValida
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import useToast from 'hooks/useToast';
import React, { useContext } from 'react';
import { useNavigate } from 'react-router-dom';
import { formatUnknownError } from 'utils/formatUnknownError';
import { useSegmentForm } from '../hooks/useSegmentForm';

View File

@ -162,7 +162,7 @@ const COLUMNS = [
{
Header: 'Name',
accessor: 'name',
width: '80%',
width: '60%',
Cell: ({ value, row: { original } }: any) => (
<HighlightCell value={value} subtitle={original.description} />
),
@ -177,6 +177,7 @@ const COLUMNS = [
{
Header: 'Created by',
accessor: 'createdBy',
width: '25%',
},
{
Header: 'Actions',

View File

@ -4,7 +4,11 @@ export const useStyles = makeStyles()(theme => ({
paramsContainer: {
maxWidth: '400px',
},
divider: { borderStyle: 'dashed', marginBottom: '1rem !important' },
divider: {
borderStyle: 'dashed',
marginBottom: '1rem !important',
borderColor: theme.palette.grey[500],
},
nameContainer: {
display: 'flex',
alignItems: 'center',

View File

@ -1,4 +1,10 @@
import { Checkbox, FormControlLabel, IconButton, Tooltip } from '@mui/material';
import {
Checkbox,
Divider,
FormControlLabel,
IconButton,
Tooltip,
} from '@mui/material';
import { Delete } from '@mui/icons-material';
import { useStyles } from './StrategyParameter.styles';
import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
@ -69,7 +75,7 @@ export const StrategyParameter = ({
return (
<div className={styles.paramsContainer}>
<hr className={styles.divider} />
<Divider className={styles.divider} />
<ConditionallyRender
condition={index === 0}
show={

View File

@ -5,6 +5,7 @@ import {
ListItemAvatar,
ListItemText,
Tooltip,
useTheme,
} from '@mui/material';
import { Add, RadioButtonChecked } from '@mui/icons-material';
import { AppsLinkList } from 'component/common';
@ -26,6 +27,7 @@ export const StrategyDetails = ({
applications,
toggles,
}: IStrategyDetailsProps) => {
const theme = useTheme();
const { parameters = [] } = strategy;
const renderParameters = (params: IStrategyParameter[]) => {
if (params.length > 0) {
@ -70,7 +72,9 @@ export const StrategyDetails = ({
condition={strategy.deprecated}
show={
<Grid item>
<h5 style={{ color: '#ff0000' }}>Deprecated</h5>
<h5 style={{ color: theme.palette.error.main }}>
Deprecated
</h5>
</Grid>
}
/>

View File

@ -35,7 +35,7 @@ exports[`renders an empty list correctly 1`] = `
className="tss-119iiqp-container"
>
<div
className="tss-1mtd8gr-search search-container"
className="tss-1xjrf9m-search search-container"
>
<svg
aria-hidden={true}