mirror of
https://github.com/Unleash/unleash.git
synced 2025-11-10 01:19:53 +01:00
refactor: fix misc TS errors (#729)
* refactor: update test deps * refactor: remove unused ts-expect-error annotations * refactor: add missing arg and return types * refactor: the loading prop is optional * refactor: add missing arg and return types * reafactor: fix value arg type * refactor: fix missing array type * refactor: the parameters field is an array * refactor: use undefined instead of null in state * refactor: add missing params type * refactor: add missing children prop * refactor: add missing array type * refactor: add missing React imports * refactor: use correct IProjectEnvironment type * refactor: type errors as unknown * refactor: the index prop is required * refactor: fix date prop type * refactor: fix tooltip placement prop type * refactor: fix environments state type * refactor: add missing arg types * refactor: add guard for undefined field * refactor: fix ChangePassword prop types * refactor: fix MUI import paths * refactor: add missing arg type * refactor: fix showDialog prop type * refactor: remove unused openUpdateDialog prop * refactor: add missing non-null assertion * refactor: remove unused types prop * refactor: stricten API error handler types * refactor: add missing undefined check * refactor: add missing IProject id field * refactor: fix ConditionallyRender condition prop types * refactor: remove unused args * refactor: add AddVariant prop types * refactor: add types to UIContext * refactor: fix event arg type * refactor: add missing default impressionData field * refactor: fix handleDeleteEnvironment prop args * refactor: fix IFeatureMetrics field requirements * refactor: add missing element types to ConditionallyRender * refactor: remove unused ProjectAccess projectId prop * refactor: add missing undefined check * refactor: fix getCreateTogglePath arg type * refactor: add missing IStrategyPayload import * refactor: remove unused user arg * refactor: add missing event arg type * refactor: add missing style object types * refactor: improve userApiErrors prop type * refactor: the Dialogue onClose prop is optional * refactor: fix the AddonEvents setEventValue prop type
This commit is contained in:
parent
a4dab966a3
commit
3959e846e8
@ -42,6 +42,7 @@
|
|||||||
"@material-ui/core": "4.12.3",
|
"@material-ui/core": "4.12.3",
|
||||||
"@material-ui/icons": "4.11.2",
|
"@material-ui/icons": "4.11.2",
|
||||||
"@material-ui/lab": "4.0.0-alpha.60",
|
"@material-ui/lab": "4.0.0-alpha.60",
|
||||||
|
"@testing-library/dom": "^8.11.3",
|
||||||
"@testing-library/jest-dom": "5.16.2",
|
"@testing-library/jest-dom": "5.16.2",
|
||||||
"@testing-library/react": "12.1.3",
|
"@testing-library/react": "12.1.3",
|
||||||
"@testing-library/user-event": "13.5.0",
|
"@testing-library/user-event": "13.5.0",
|
||||||
@ -49,7 +50,7 @@
|
|||||||
"@types/deep-diff": "1.0.1",
|
"@types/deep-diff": "1.0.1",
|
||||||
"@types/jest": "27.4.1",
|
"@types/jest": "27.4.1",
|
||||||
"@types/lodash.clonedeep": "4.5.6",
|
"@types/lodash.clonedeep": "4.5.6",
|
||||||
"@types/node": "14.18.12",
|
"@types/node": "17.0.18",
|
||||||
"@types/react": "17.0.39",
|
"@types/react": "17.0.39",
|
||||||
"@types/react-dom": "17.0.11",
|
"@types/react-dom": "17.0.11",
|
||||||
"@types/react-outside-click-handler": "1.3.1",
|
"@types/react-outside-click-handler": "1.3.1",
|
||||||
@ -63,7 +64,7 @@
|
|||||||
"copy-to-clipboard": "3.3.1",
|
"copy-to-clipboard": "3.3.1",
|
||||||
"craco": "0.0.3",
|
"craco": "0.0.3",
|
||||||
"css-loader": "6.6.0",
|
"css-loader": "6.6.0",
|
||||||
"cypress": "8.7.0",
|
"cypress": "9.5.0",
|
||||||
"date-fns": "2.28.0",
|
"date-fns": "2.28.0",
|
||||||
"debounce": "1.2.1",
|
"debounce": "1.2.1",
|
||||||
"deep-diff": "1.0.2",
|
"deep-diff": "1.0.2",
|
||||||
@ -82,7 +83,7 @@
|
|||||||
"react-outside-click-handler": "1.3.0",
|
"react-outside-click-handler": "1.3.0",
|
||||||
"react-router-dom": "5.3.0",
|
"react-router-dom": "5.3.0",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
"react-test-renderer": "16.14.0",
|
"react-test-renderer": "17.0.2",
|
||||||
"react-timeago": "6.2.1",
|
"react-timeago": "6.2.1",
|
||||||
"sass": "1.49.8",
|
"sass": "1.49.8",
|
||||||
"swr": "1.2.2",
|
"swr": "1.2.2",
|
||||||
|
|||||||
@ -7,7 +7,9 @@ import { IAddonProvider } from '../../../../interfaces/addons';
|
|||||||
interface IAddonProps {
|
interface IAddonProps {
|
||||||
provider: IAddonProvider;
|
provider: IAddonProvider;
|
||||||
checkedEvents: string[];
|
checkedEvents: string[];
|
||||||
setEventValue: (name: string) => void;
|
setEventValue: (
|
||||||
|
name: string
|
||||||
|
) => (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
error: Record<string, string>;
|
error: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ReactElement } from 'react';
|
import React, { ReactElement } from 'react';
|
||||||
import { ConfiguredAddons } from './ConfiguredAddons/ConfiguredAddons';
|
import { ConfiguredAddons } from './ConfiguredAddons/ConfiguredAddons';
|
||||||
import { AvailableAddons } from './AvailableAddons/AvailableAddons';
|
import { AvailableAddons } from './AvailableAddons/AvailableAddons';
|
||||||
import { Avatar } from '@material-ui/core';
|
import { Avatar } from '@material-ui/core';
|
||||||
@ -12,7 +12,7 @@ import dataDogIcon from '../../../assets/icons/datadog.svg';
|
|||||||
import { formatAssetPath } from '../../../utils/format-path';
|
import { formatAssetPath } from '../../../utils/format-path';
|
||||||
import useAddons from '../../../hooks/api/getters/useAddons/useAddons';
|
import useAddons from '../../../hooks/api/getters/useAddons/useAddons';
|
||||||
|
|
||||||
const style = {
|
const style: React.CSSProperties = {
|
||||||
width: '40px',
|
width: '40px',
|
||||||
height: '40px',
|
height: '40px',
|
||||||
marginRight: '16px',
|
marginRight: '16px',
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import AccessContext from '../../../../contexts/AccessContext';
|
|||||||
import { IAddon } from '../../../../interfaces/addons';
|
import { IAddon } from '../../../../interfaces/addons';
|
||||||
import PermissionIconButton from '../../../common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from '../../../common/PermissionIconButton/PermissionIconButton';
|
||||||
import Dialogue from '../../../common/Dialogue';
|
import Dialogue from '../../../common/Dialogue';
|
||||||
|
import { formatUnknownError } from '../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
interface IConfigureAddonsProps {
|
interface IConfigureAddonsProps {
|
||||||
getAddonIcon: (name: string) => ReactElement;
|
getAddonIcon: (name: string) => ReactElement;
|
||||||
@ -59,8 +60,8 @@ export const ConfiguredAddons = ({ getAddonIcon }: IConfigureAddonsProps) => {
|
|||||||
title: 'Success',
|
title: 'Success',
|
||||||
text: 'Addon state switched successfully',
|
text: 'Addon state switched successfully',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
|||||||
import { ConfirmToken } from '../ConfirmToken/ConfirmToken';
|
import { ConfirmToken } from '../ConfirmToken/ConfirmToken';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { scrollToTop } from '../../../common/util';
|
import { scrollToTop } from '../../../common/util';
|
||||||
|
import { formatUnknownError } from '../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
export const CreateApiToken = () => {
|
export const CreateApiToken = () => {
|
||||||
const { setToastApiError } = useToast();
|
const { setToastApiError } = useToast();
|
||||||
@ -49,8 +50,8 @@ export const CreateApiToken = () => {
|
|||||||
setToken(api.secret);
|
setToken(api.secret);
|
||||||
setShowConfirm(true);
|
setShowConfirm(true);
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -68,8 +68,8 @@ export const GoogleAuth = () => {
|
|||||||
title: 'Settings stored',
|
title: 'Settings stored',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(err));
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -79,8 +79,8 @@ export const OidcAuth = () => {
|
|||||||
title: 'Settings stored',
|
title: 'Settings stored',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(err));
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -51,8 +51,8 @@ export const PasswordAuth = () => {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
show: true,
|
show: true,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(err));
|
setToastApiError(formatUnknownError(error));
|
||||||
setDisablePasswordAuth(config.disabled);
|
setDisablePasswordAuth(config.disabled);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -75,8 +75,8 @@ export const SamlAuth = () => {
|
|||||||
title: 'Settings stored',
|
title: 'Settings stored',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(err));
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
|||||||
import useToast from '../../../../hooks/useToast';
|
import useToast from '../../../../hooks/useToast';
|
||||||
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
||||||
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
||||||
|
import { formatUnknownError } from '../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const CreateProjectRole = () => {
|
const CreateProjectRole = () => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
@ -49,8 +50,8 @@ const CreateProjectRole = () => {
|
|||||||
confetti: true,
|
confetti: true,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
|||||||
import useToast from '../../../../hooks/useToast';
|
import useToast from '../../../../hooks/useToast';
|
||||||
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
||||||
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
||||||
|
import { formatUnknownError } from '../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const EditProjectRole = () => {
|
const EditProjectRole = () => {
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
@ -88,8 +89,8 @@ const EditProjectRole = () => {
|
|||||||
text: 'Your role changes will automatically be applied to the users with this role.',
|
text: 'Your role changes will automatically be applied to the users with this role.',
|
||||||
confetti: true,
|
confetti: true,
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
import Input from '../../../common/Input/Input';
|
import Input from '../../../common/Input/Input';
|
||||||
import EnvironmentPermissionAccordion from './EnvironmentPermissionAccordion/EnvironmentPermissionAccordion';
|
import EnvironmentPermissionAccordion from './EnvironmentPermissionAccordion/EnvironmentPermissionAccordion';
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
TextField,
|
TextField,
|
||||||
Button,
|
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import useProjectRolePermissions from '../../../../hooks/api/getters/useProjectRolePermissions/useProjectRolePermissions';
|
import useProjectRolePermissions from '../../../../hooks/api/getters/useProjectRolePermissions/useProjectRolePermissions';
|
||||||
|
|
||||||
import { useStyles } from './ProjectRoleForm.styles';
|
import { useStyles } from './ProjectRoleForm.styles';
|
||||||
import ConditionallyRender from '../../../common/ConditionallyRender';
|
import ConditionallyRender from '../../../common/ConditionallyRender';
|
||||||
import React from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import { IPermission } from '../../../../interfaces/project';
|
import { IPermission } from '../../../../interfaces/project';
|
||||||
import {
|
import {
|
||||||
ICheckedPermission,
|
ICheckedPermission,
|
||||||
@ -33,6 +33,7 @@ interface IProjectRoleForm {
|
|||||||
clearErrors: () => void;
|
clearErrors: () => void;
|
||||||
validateNameUniqueness?: () => void;
|
validateNameUniqueness?: () => void;
|
||||||
getRoleKey: (permission: { id: number; environment?: string }) => string;
|
getRoleKey: (permission: { id: number; environment?: string }) => string;
|
||||||
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProjectRoleForm: React.FC<IProjectRoleForm> = ({
|
const ProjectRoleForm: React.FC<IProjectRoleForm> = ({
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(theme => ({
|
export const useStyles = makeStyles(theme => ({
|
||||||
deleteParagraph: {
|
deleteParagraph: {
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import IRole, { IProjectRole } from '../../../../../interfaces/role';
|
|||||||
import useProjectRolesApi from '../../../../../hooks/api/actions/useProjectRolesApi/useProjectRolesApi';
|
import useProjectRolesApi from '../../../../../hooks/api/actions/useProjectRolesApi/useProjectRolesApi';
|
||||||
import useToast from '../../../../../hooks/useToast';
|
import useToast from '../../../../../hooks/useToast';
|
||||||
import ProjectRoleDeleteConfirm from '../ProjectRoleDeleteConfirm/ProjectRoleDeleteConfirm';
|
import ProjectRoleDeleteConfirm from '../ProjectRoleDeleteConfirm/ProjectRoleDeleteConfirm';
|
||||||
|
import { formatUnknownError } from '../../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const ROOTROLE = 'root';
|
const ROOTROLE = 'root';
|
||||||
|
|
||||||
@ -44,8 +45,8 @@ const ProjectRoleList = () => {
|
|||||||
title: 'Successfully deleted role',
|
title: 'Successfully deleted role',
|
||||||
text: 'Your role is now deleted',
|
text: 'Your role is now deleted',
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
setDelDialog(false);
|
setDelDialog(false);
|
||||||
setConfirmName('');
|
setConfirmName('');
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import { useStyles } from './ProjectRoleListItem.styles';
|
import { useStyles } from './ProjectRoleListItem.styles';
|
||||||
import { TableRow, TableCell, Typography } from '@material-ui/core';
|
import { TableCell, TableRow, Typography } from '@material-ui/core';
|
||||||
import { Edit, Delete } from '@material-ui/icons';
|
import { Delete, Edit } from '@material-ui/icons';
|
||||||
import { ADMIN } from '../../../../../providers/AccessProvider/permissions';
|
import { ADMIN } from '../../../../../providers/AccessProvider/permissions';
|
||||||
import SupervisedUserCircleIcon from '@material-ui/icons/SupervisedUserCircle';
|
import SupervisedUserCircleIcon from '@material-ui/icons/SupervisedUserCircle';
|
||||||
import PermissionIconButton from '../../../../../common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from '../../../../../common/PermissionIconButton/PermissionIconButton';
|
||||||
import { IProjectRole } from '../../../../../../interfaces/role';
|
import { IProjectRole } from '../../../../../../interfaces/role';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface IRoleListItemProps {
|
interface IRoleListItemProps {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(theme => ({
|
export const useStyles = makeStyles(theme => ({
|
||||||
rolesListBody: {
|
rolesListBody: {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
export const useStyles = makeStyles({
|
export const useStyles = makeStyles({
|
||||||
iconContainer: {
|
iconContainer: {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { useState } from 'react';
|
|||||||
import { scrollToTop } from '../../../common/util';
|
import { scrollToTop } from '../../../common/util';
|
||||||
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
||||||
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
||||||
|
import { formatUnknownError } from '../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const CreateUser = () => {
|
const CreateUser = () => {
|
||||||
const { setToastApiError } = useToast();
|
const { setToastApiError } = useToast();
|
||||||
@ -51,8 +52,8 @@ const CreateUser = () => {
|
|||||||
setInviteLink(user.inviteLink);
|
setInviteLink(user.inviteLink);
|
||||||
setShowConfirm(true);
|
setShowConfirm(true);
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { useEffect } from 'react';
|
|||||||
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
||||||
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
||||||
import { EDIT } from '../../../../constants/misc';
|
import { EDIT } from '../../../../constants/misc';
|
||||||
|
import { formatUnknownError } from '../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const EditUser = () => {
|
const EditUser = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -60,8 +61,8 @@ const EditUser = () => {
|
|||||||
title: 'User information updated',
|
title: 'User information updated',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(theme => ({
|
export const useStyles = makeStyles(theme => ({
|
||||||
userListBody: {
|
userListBody: {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { TextField, Typography, Avatar } from '@material-ui/core';
|
import { Avatar, TextField, Typography } from '@material-ui/core';
|
||||||
import { trim } from '../../../../common/util';
|
import { trim } from '../../../../common/util';
|
||||||
import { modalStyles } from '../../util';
|
import { modalStyles } from '../../util';
|
||||||
import Dialogue from '../../../../common/Dialogue/Dialogue';
|
import Dialogue from '../../../../common/Dialogue/Dialogue';
|
||||||
@ -12,10 +12,10 @@ import { Alert } from '@material-ui/lab';
|
|||||||
import { IUser } from '../../../../../interfaces/user';
|
import { IUser } from '../../../../../interfaces/user';
|
||||||
|
|
||||||
interface IChangePasswordProps {
|
interface IChangePasswordProps {
|
||||||
showDialog: () => void;
|
showDialog: boolean;
|
||||||
closeDialog: () => void;
|
closeDialog: () => void;
|
||||||
changePassword: () => void;
|
changePassword: (user: IUser, password: string) => Promise<Response>;
|
||||||
user: IUser;
|
user: Partial<IUser>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChangePassword = ({
|
const ChangePassword = ({
|
||||||
@ -25,7 +25,7 @@ const ChangePassword = ({
|
|||||||
user = {},
|
user = {},
|
||||||
}: IChangePasswordProps) => {
|
}: IChangePasswordProps) => {
|
||||||
const [data, setData] = useState({});
|
const [data, setData] = useState({});
|
||||||
const [error, setError] = useState({});
|
const [error, setError] = useState<Record<string, string>>({});
|
||||||
const [validPassword, setValidPassword] = useState(false);
|
const [validPassword, setValidPassword] = useState(false);
|
||||||
const commonStyles = useCommonStyles();
|
const commonStyles = useCommonStyles();
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ const ChangePassword = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={error.general}
|
condition={Boolean(error.general)}
|
||||||
show={<Alert severity="error">{error.general}</Alert>}
|
show={<Alert severity="error">{error.general}</Alert>}
|
||||||
/>
|
/>
|
||||||
<Typography variant="subtitle1">
|
<Typography variant="subtitle1">
|
||||||
|
|||||||
@ -9,12 +9,12 @@ import { useCommonStyles } from '../../../../../common.styles';
|
|||||||
import { IUser } from '../../../../../interfaces/user';
|
import { IUser } from '../../../../../interfaces/user';
|
||||||
|
|
||||||
interface IDeleteUserProps {
|
interface IDeleteUserProps {
|
||||||
showDialog: () => void;
|
showDialog: boolean;
|
||||||
closeDialog: () => void;
|
closeDialog: () => void;
|
||||||
user: IUser;
|
user: IUser;
|
||||||
userLoading: boolean;
|
userLoading: boolean;
|
||||||
removeUser: () => void;
|
removeUser: () => void;
|
||||||
userApiErrors: Object;
|
userApiErrors: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeleteUser = ({
|
const DeleteUser = ({
|
||||||
@ -33,13 +33,13 @@ const DeleteUser = ({
|
|||||||
open={showDialog}
|
open={showDialog}
|
||||||
title="Really delete user?"
|
title="Really delete user?"
|
||||||
onClose={closeDialog}
|
onClose={closeDialog}
|
||||||
onClick={() => removeUser(user)}
|
onClick={removeUser}
|
||||||
primaryButtonText="Delete user"
|
primaryButtonText="Delete user"
|
||||||
secondaryButtonText="Cancel"
|
secondaryButtonText="Cancel"
|
||||||
>
|
>
|
||||||
<div ref={ref}>
|
<div ref={ref}>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={userApiErrors[REMOVE_USER_ERROR]}
|
condition={Boolean(userApiErrors[REMOVE_USER_ERROR])}
|
||||||
show={
|
show={
|
||||||
<Alert
|
<Alert
|
||||||
data-loading
|
data-loading
|
||||||
|
|||||||
@ -19,7 +19,6 @@ import { formatDateYMD } from '../../../../../utils/format-date';
|
|||||||
interface IUserListItemProps {
|
interface IUserListItemProps {
|
||||||
user: IUser;
|
user: IUser;
|
||||||
renderRole: (roleId: number) => string;
|
renderRole: (roleId: number) => string;
|
||||||
openUpdateDialog: (user: IUser) => (e: SyntheticEvent) => void;
|
|
||||||
openPwDialog: (user: IUser) => (e: SyntheticEvent) => void;
|
openPwDialog: (user: IUser) => (e: SyntheticEvent) => void;
|
||||||
openDelDialog: (user: IUser) => (e: SyntheticEvent) => void;
|
openDelDialog: (user: IUser) => (e: SyntheticEvent) => void;
|
||||||
locationSettings: ILocationSettings;
|
locationSettings: ILocationSettings;
|
||||||
@ -30,7 +29,6 @@ const UserListItem = ({
|
|||||||
renderRole,
|
renderRole,
|
||||||
openDelDialog,
|
openDelDialog,
|
||||||
openPwDialog,
|
openPwDialog,
|
||||||
openUpdateDialog,
|
|
||||||
locationSettings,
|
locationSettings,
|
||||||
}: IUserListItemProps) => {
|
}: IUserListItemProps) => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import { IUser } from '../../../../interfaces/user';
|
|||||||
import IRole from '../../../../interfaces/role';
|
import IRole from '../../../../interfaces/role';
|
||||||
import useToast from '../../../../hooks/useToast';
|
import useToast from '../../../../hooks/useToast';
|
||||||
import { useLocationSettings } from '../../../../hooks/useLocationSettings';
|
import { useLocationSettings } from '../../../../hooks/useLocationSettings';
|
||||||
|
import { formatUnknownError } from '../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const UsersList = () => {
|
const UsersList = () => {
|
||||||
const { users, roles, refetch, loading } = useUsers();
|
const { users, roles, refetch, loading } = useUsers();
|
||||||
@ -79,8 +80,8 @@ const UsersList = () => {
|
|||||||
});
|
});
|
||||||
refetch();
|
refetch();
|
||||||
closeDelDialog();
|
closeDelDialog();
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -172,7 +173,7 @@ const UsersList = () => {
|
|||||||
<DeleteUser
|
<DeleteUser
|
||||||
showDialog={delDialog}
|
showDialog={delDialog}
|
||||||
closeDialog={closeDelDialog}
|
closeDialog={closeDelDialog}
|
||||||
user={delUser}
|
user={delUser!}
|
||||||
removeUser={onDeleteUser}
|
removeUser={onDeleteUser}
|
||||||
userLoading={userLoading}
|
userLoading={userLoading}
|
||||||
userApiErrors={userApiErrors}
|
userApiErrors={userApiErrors}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
/* eslint react/no-multi-comp:off */
|
/* eslint react/no-multi-comp:off */
|
||||||
import { useContext, useState } from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
Link,
|
|
||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
LinearProgress,
|
LinearProgress,
|
||||||
|
Link,
|
||||||
Typography,
|
Typography,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import { Link as LinkIcon } from '@material-ui/icons';
|
import { Link as LinkIcon } from '@material-ui/icons';
|
||||||
@ -25,6 +25,7 @@ import { useLocationSettings } from '../../../hooks/useLocationSettings';
|
|||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
||||||
import { formatDateYMD } from '../../../utils/format-date';
|
import { formatDateYMD } from '../../../utils/format-date';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
export const ApplicationEdit = () => {
|
export const ApplicationEdit = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@ -44,7 +45,7 @@ export const ApplicationEdit = () => {
|
|||||||
|
|
||||||
const formatDate = (v: string) => formatDateYMD(v, locationSettings.locale);
|
const formatDate = (v: string) => formatDateYMD(v, locationSettings.locale);
|
||||||
|
|
||||||
const onDeleteApplication = async (evt: Event) => {
|
const onDeleteApplication = async (evt: React.SyntheticEvent) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
try {
|
try {
|
||||||
await deleteApplication(appName);
|
await deleteApplication(appName);
|
||||||
@ -54,8 +55,8 @@ export const ApplicationEdit = () => {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
history.push('/applications');
|
history.push('/applications');
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ChangeEvent, useState } from 'react';
|
import { ChangeEvent, useState } from 'react';
|
||||||
import { TextField, Grid } from '@material-ui/core';
|
import { Grid, TextField } from '@material-ui/core';
|
||||||
import { useCommonStyles } from '../../../common.styles';
|
import { useCommonStyles } from '../../../common.styles';
|
||||||
import icons from '../icon-names';
|
import icons from '../icon-names';
|
||||||
import GeneralSelect from '../../common/GeneralSelect/GeneralSelect';
|
import GeneralSelect from '../../common/GeneralSelect/GeneralSelect';
|
||||||
@ -7,6 +7,7 @@ import useApplicationsApi from '../../../hooks/api/actions/useApplicationsApi/us
|
|||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
import { IApplication } from '../../../interfaces/application';
|
import { IApplication } from '../../../interfaces/application';
|
||||||
import useApplication from '../../../hooks/api/getters/useApplication/useApplication';
|
import useApplication from '../../../hooks/api/getters/useApplication/useApplication';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
interface IApplicationUpdateProps {
|
interface IApplicationUpdateProps {
|
||||||
application: IApplication;
|
application: IApplication;
|
||||||
@ -35,8 +36,8 @@ export const ApplicationUpdate = ({ application }: IApplicationUpdateProps) => {
|
|||||||
title: 'Updated Successfully',
|
title: 'Updated Successfully',
|
||||||
text: `${field} successfully updated`,
|
text: `${field} successfully updated`,
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -4,16 +4,16 @@ import {
|
|||||||
Grid,
|
Grid,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemText,
|
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
|
ListItemText,
|
||||||
Typography,
|
Typography,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import {
|
import {
|
||||||
Report,
|
|
||||||
Extension,
|
Extension,
|
||||||
Timeline,
|
|
||||||
FlagRounded,
|
FlagRounded,
|
||||||
|
Report,
|
||||||
SvgIconComponent,
|
SvgIconComponent,
|
||||||
|
Timeline,
|
||||||
} from '@material-ui/icons';
|
} from '@material-ui/icons';
|
||||||
import {
|
import {
|
||||||
CREATE_FEATURE,
|
CREATE_FEATURE,
|
||||||
@ -117,10 +117,9 @@ export const ApplicationView = () => {
|
|||||||
createUrl: `/projects/default/create-toggle?name=${name}`,
|
createUrl: `/projects/default/create-toggle?name=${name}`,
|
||||||
name,
|
name,
|
||||||
permission: CREATE_FEATURE,
|
permission: CREATE_FEATURE,
|
||||||
i,
|
|
||||||
})}
|
})}
|
||||||
elseShow={foundListItem({
|
elseShow={foundListItem({
|
||||||
viewUrl: getTogglePath(project, name, true),
|
viewUrl: getTogglePath(project, name),
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
Icon: FlagRounded,
|
Icon: FlagRounded,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState, useRef, FC } from 'react';
|
import React, { useEffect, useState, useRef, FC } from 'react';
|
||||||
import ConditionallyRender from '../ConditionallyRender';
|
import ConditionallyRender from '../ConditionallyRender';
|
||||||
|
|
||||||
interface IAnimateOnMountProps {
|
interface IAnimateOnMountProps {
|
||||||
@ -7,7 +7,7 @@ interface IAnimateOnMountProps {
|
|||||||
start: string;
|
start: string;
|
||||||
leave: string;
|
leave: string;
|
||||||
container?: string;
|
container?: string;
|
||||||
style?: Object;
|
style?: React.CSSProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AnimateOnMount: FC<IAnimateOnMountProps> = ({
|
const AnimateOnMount: FC<IAnimateOnMountProps> = ({
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Button } from '@material-ui/core';
|
import { Button } from '@material-ui/core';
|
||||||
import { Alert } from '@material-ui/lab';
|
import { Alert } from '@material-ui/lab';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface IApiErrorProps {
|
interface IApiErrorProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
interface IConditionallyRenderProps {
|
interface IConditionallyRenderProps {
|
||||||
condition: boolean;
|
condition: boolean;
|
||||||
show: JSX.Element | RenderFunc;
|
show: TargetElement;
|
||||||
elseShow?: JSX.Element | RenderFunc;
|
elseShow?: TargetElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TargetElement = JSX.Element | JSX.Element[] | RenderFunc | null;
|
||||||
type RenderFunc = () => JSX.Element;
|
type RenderFunc = () => JSX.Element;
|
||||||
|
|
||||||
const ConditionallyRender = ({
|
const ConditionallyRender = ({
|
||||||
@ -23,8 +24,9 @@ const ConditionallyRender = ({
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isFunc = (param: JSX.Element | RenderFunc) =>
|
const isFunc = (param: TargetElement): boolean => {
|
||||||
typeof param === 'function';
|
return typeof param === 'function';
|
||||||
|
};
|
||||||
|
|
||||||
if (condition) {
|
if (condition) {
|
||||||
if (isFunc(show)) {
|
if (isFunc(show)) {
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogTitle,
|
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
Button,
|
DialogTitle,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
|
|
||||||
import ConditionallyRender from '../ConditionallyRender/ConditionallyRender';
|
import ConditionallyRender from '../ConditionallyRender/ConditionallyRender';
|
||||||
@ -15,15 +15,15 @@ interface IDialogue {
|
|||||||
primaryButtonText?: string;
|
primaryButtonText?: string;
|
||||||
secondaryButtonText?: string;
|
secondaryButtonText?: string;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClick: (e: any) => void;
|
onClick: (e: React.SyntheticEvent) => void;
|
||||||
onClose: () => void;
|
onClose?: (e: React.SyntheticEvent) => void;
|
||||||
style?: object;
|
style?: object;
|
||||||
title: string;
|
title: string;
|
||||||
fullWidth?: boolean;
|
fullWidth?: boolean;
|
||||||
maxWidth?: 'lg' | 'sm' | 'xs' | 'md' | 'xl';
|
maxWidth?: 'lg' | 'sm' | 'xs' | 'md' | 'xl';
|
||||||
disabledPrimaryButton?: boolean;
|
disabledPrimaryButton?: boolean;
|
||||||
formId?: string;
|
formId?: string;
|
||||||
permissionButton?: React.ReactNode;
|
permissionButton?: JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Dialogue: React.FC<IDialogue> = ({
|
const Dialogue: React.FC<IDialogue> = ({
|
||||||
@ -69,7 +69,7 @@ const Dialogue: React.FC<IDialogue> = ({
|
|||||||
<DialogActions>
|
<DialogActions>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(permissionButton)}
|
condition={Boolean(permissionButton)}
|
||||||
show={permissionButton}
|
show={permissionButton!}
|
||||||
elseShow={
|
elseShow={
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(onClick)}
|
condition={Boolean(onClick)}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface EnvironmentSplashPageProps {
|
interface EnvironmentSplashPageProps {
|
||||||
title: React.ReactNode;
|
title: React.ReactNode;
|
||||||
topDescription: React.ReactNode;
|
topDescription: React.ReactNode;
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import ConditionallyRender from '../ConditionallyRender';
|
|||||||
import Loader from '../Loader/Loader';
|
import Loader from '../Loader/Loader';
|
||||||
import copy from 'copy-to-clipboard';
|
import copy from 'copy-to-clipboard';
|
||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface ICreateProps {
|
interface ICreateProps {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface IGradientProps {
|
interface IGradientProps {
|
||||||
from: string;
|
from: string;
|
||||||
to: string;
|
to: string;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { TextField } from '@material-ui/core';
|
import { TextField } from '@material-ui/core';
|
||||||
import { INPUT_ERROR_TEXT } from '../../../testIds';
|
import { INPUT_ERROR_TEXT } from '../../../testIds';
|
||||||
import { useStyles } from './Input.styles.ts';
|
import { useStyles } from './Input.styles';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface IInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
interface IInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||||
label: string;
|
label: string;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { ReactComponent as NoItemsIcon } from '../../../assets/icons/addfiles.svg';
|
import { ReactComponent as NoItemsIcon } from '../../../assets/icons/addfiles.svg';
|
||||||
import { useStyles } from './NoItems.styles';
|
import { useStyles } from './NoItems.styles';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
const NoItems: React.FC = ({ children }) => {
|
const NoItems: React.FC = ({ children }) => {
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import ConditionallyRender from '../ConditionallyRender';
|
import ConditionallyRender from '../ConditionallyRender';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { useStyles } from './PaginationUI.styles';
|
import { useStyles } from './PaginationUI.styles';
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { IconButton, InputAdornment, TextField } from '@material-ui/core';
|
import { IconButton, InputAdornment, TextField } from '@material-ui/core';
|
||||||
import { Visibility, VisibilityOff } from '@material-ui/icons';
|
import { Visibility, VisibilityOff } from '@material-ui/icons';
|
||||||
import { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
const PasswordField = ({ ...rest }) => {
|
const PasswordField = ({ ...rest }) => {
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Button, Tooltip } from '@material-ui/core';
|
import { Button, Tooltip } from '@material-ui/core';
|
||||||
import { Lock } from '@material-ui/icons';
|
import { Lock } from '@material-ui/icons';
|
||||||
import { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import AccessContext from '../../../contexts/AccessContext';
|
import AccessContext from '../../../contexts/AccessContext';
|
||||||
import ConditionallyRender from '../ConditionallyRender';
|
import ConditionallyRender from '../ConditionallyRender';
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { IconButton, Tooltip } from '@material-ui/core';
|
import { IconButton, Tooltip } from '@material-ui/core';
|
||||||
import { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import AccessContext from '../../../contexts/AccessContext';
|
import AccessContext from '../../../contexts/AccessContext';
|
||||||
|
|
||||||
interface IPermissionIconButtonProps
|
interface IPermissionIconButtonProps
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { useMediaQuery } from '@material-ui/core';
|
|||||||
import ConditionallyRender from '../ConditionallyRender';
|
import ConditionallyRender from '../ConditionallyRender';
|
||||||
import PermissionButton from '../PermissionButton/PermissionButton';
|
import PermissionButton from '../PermissionButton/PermissionButton';
|
||||||
import PermissionIconButton from '../PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from '../PermissionIconButton/PermissionIconButton';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface IResponsiveButtonProps {
|
interface IResponsiveButtonProps {
|
||||||
Icon: React.ElementType;
|
Icon: React.ElementType;
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
import { Fragment } from 'react';
|
import React, { Fragment, useState } from 'react';
|
||||||
import { Button, IconButton } from '@material-ui/core';
|
import { Button, IconButton } from '@material-ui/core';
|
||||||
import { useStyles } from './Splash.styles';
|
import { useStyles } from './Splash.styles';
|
||||||
import {
|
import {
|
||||||
|
CloseOutlined,
|
||||||
FiberManualRecord,
|
FiberManualRecord,
|
||||||
FiberManualRecordOutlined,
|
FiberManualRecordOutlined,
|
||||||
CloseOutlined,
|
|
||||||
} from '@material-ui/icons';
|
} from '@material-ui/icons';
|
||||||
import { useState } from 'react';
|
|
||||||
import ConditionallyRender from '../ConditionallyRender';
|
import ConditionallyRender from '../ConditionallyRender';
|
||||||
import { CLOSE_SPLASH } from '../../../testIds';
|
import { CLOSE_SPLASH } from '../../../testIds';
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ interface ITagSelect extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
|||||||
onChange: (val: any) => void;
|
onChange: (val: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TagSelect = ({ value, types, onChange, ...rest }: ITagSelect) => {
|
const TagSelect = ({ value, onChange, ...rest }: ITagSelect) => {
|
||||||
const { tagTypes } = useTagTypes();
|
const { tagTypes } = useTagTypes();
|
||||||
|
|
||||||
const options = tagTypes.map(tagType => ({
|
const options = tagTypes.map(tagType => ({
|
||||||
|
|||||||
@ -3,12 +3,12 @@ import classnames from 'classnames';
|
|||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { IconButton } from '@material-ui/core';
|
import { IconButton } from '@material-ui/core';
|
||||||
import CheckMarkBadge from '../../CheckmarkBadge/CheckMarkBadge';
|
import CheckMarkBadge from '../../CheckmarkBadge/CheckMarkBadge';
|
||||||
import UIContext, { IToastData } from '../../../../contexts/UIContext';
|
import UIContext from '../../../../contexts/UIContext';
|
||||||
import ConditionallyRender from '../../ConditionallyRender';
|
import ConditionallyRender from '../../ConditionallyRender';
|
||||||
import Close from '@material-ui/icons/Close';
|
import Close from '@material-ui/icons/Close';
|
||||||
|
import { IToast } from '../../../../interfaces/toast';
|
||||||
|
|
||||||
const Toast = ({ title, text, type, confetti }: IToastData) => {
|
const Toast = ({ title, text, type, confetti }: IToast) => {
|
||||||
// @ts-expect-error
|
|
||||||
const { setToast } = useContext(UIContext);
|
const { setToast } = useContext(UIContext);
|
||||||
|
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
@ -51,7 +51,7 @@ const Toast = ({ title, text, type, confetti }: IToastData) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const hide = () => {
|
const hide = () => {
|
||||||
setToast((prev: IToastData) => ({ ...prev, show: false }));
|
setToast((prev: IToast) => ({ ...prev, show: false }));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,19 +1,19 @@
|
|||||||
import { Portal } from '@material-ui/core';
|
import { Portal } from '@material-ui/core';
|
||||||
import { useContext, useEffect } from 'react';
|
import { useContext, useEffect } from 'react';
|
||||||
import { useCommonStyles } from '../../../common.styles';
|
import { useCommonStyles } from '../../../common.styles';
|
||||||
import UIContext, { IToastData } from '../../../contexts/UIContext';
|
import UIContext from '../../../contexts/UIContext';
|
||||||
import { useStyles } from './ToastRenderer.styles';
|
import { useStyles } from './ToastRenderer.styles';
|
||||||
import AnimateOnMount from '../AnimateOnMount/AnimateOnMount';
|
import AnimateOnMount from '../AnimateOnMount/AnimateOnMount';
|
||||||
import Toast from './Toast/Toast';
|
import Toast from './Toast/Toast';
|
||||||
|
import { IToast } from '../../../interfaces/toast';
|
||||||
|
|
||||||
const ToastRenderer = () => {
|
const ToastRenderer = () => {
|
||||||
// @ts-expect-error
|
|
||||||
const { toastData, setToast } = useContext(UIContext);
|
const { toastData, setToast } = useContext(UIContext);
|
||||||
const commonStyles = useCommonStyles();
|
const commonStyles = useCommonStyles();
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
|
||||||
const hide = () => {
|
const hide = () => {
|
||||||
setToast((prev: IToastData) => ({ ...prev, show: false }));
|
setToast((prev: IToast) => ({ ...prev, show: false }));
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -31,7 +31,7 @@ const ToastRenderer = () => {
|
|||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
<AnimateOnMount
|
<AnimateOnMount
|
||||||
mounted={toastData?.show}
|
mounted={Boolean(toastData?.show)}
|
||||||
start={commonStyles.fadeInBottomStartWithoutFixed}
|
start={commonStyles.fadeInBottomStartWithoutFixed}
|
||||||
enter={commonStyles.fadeInBottomEnter}
|
enter={commonStyles.fadeInBottomEnter}
|
||||||
leave={commonStyles.fadeInBottomLeave}
|
leave={commonStyles.fadeInBottomLeave}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
UPDATE_CONTEXT_FIELD,
|
UPDATE_CONTEXT_FIELD,
|
||||||
} from '../../providers/AccessProvider/permissions';
|
} from '../../providers/AccessProvider/permissions';
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
IconButton,
|
IconButton,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
@ -14,7 +15,6 @@ import {
|
|||||||
ListItemText,
|
ListItemText,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
Button,
|
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import { Add, Album, Delete, Edit } from '@material-ui/icons';
|
import { Add, Album, Delete, Edit } from '@material-ui/icons';
|
||||||
import { useContext, useState } from 'react';
|
import { useContext, useState } from 'react';
|
||||||
@ -25,6 +25,7 @@ import AccessContext from '../../../contexts/AccessContext';
|
|||||||
import useUnleashContext from '../../../hooks/api/getters/useUnleashContext/useUnleashContext';
|
import useUnleashContext from '../../../hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||||
import useContextsApi from '../../../hooks/api/actions/useContextsApi/useContextsApi';
|
import useContextsApi from '../../../hooks/api/actions/useContextsApi/useContextsApi';
|
||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const ContextList = () => {
|
const ContextList = () => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
@ -46,8 +47,8 @@ const ContextList = () => {
|
|||||||
title: 'Successfully deleted context',
|
title: 'Successfully deleted context',
|
||||||
text: 'Your context is now deleted',
|
text: 'Your context is now deleted',
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
setName(undefined);
|
setName(undefined);
|
||||||
setShowDelDialogue(false);
|
setShowDelDialogue(false);
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
|||||||
import { CREATE_CONTEXT_FIELD } from '../../providers/AccessProvider/permissions';
|
import { CREATE_CONTEXT_FIELD } from '../../providers/AccessProvider/permissions';
|
||||||
import useContextsApi from '../../../hooks/api/actions/useContextsApi/useContextsApi';
|
import useContextsApi from '../../../hooks/api/actions/useContextsApi/useContextsApi';
|
||||||
import useUnleashContext from '../../../hooks/api/getters/useUnleashContext/useUnleashContext';
|
import useUnleashContext from '../../../hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const CreateContext = () => {
|
const CreateContext = () => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
@ -46,8 +47,8 @@ const CreateContext = () => {
|
|||||||
confetti: true,
|
confetti: true,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { scrollToTop } from '../../common/util';
|
|||||||
import { UPDATE_CONTEXT_FIELD } from '../../providers/AccessProvider/permissions';
|
import { UPDATE_CONTEXT_FIELD } from '../../providers/AccessProvider/permissions';
|
||||||
import ContextForm from '../ContextForm/ContextForm';
|
import ContextForm from '../ContextForm/ContextForm';
|
||||||
import useContextForm from '../hooks/useContextForm';
|
import useContextForm from '../hooks/useContextForm';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const EditContext = () => {
|
const EditContext = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -67,8 +68,8 @@ const EditContext = () => {
|
|||||||
title: 'Context information updated',
|
title: 'Context information updated',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import HeaderTitle from '../../common/HeaderTitle';
|
|||||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
||||||
import { ADMIN } from '../../providers/AccessProvider/permissions';
|
import { ADMIN } from '../../providers/AccessProvider/permissions';
|
||||||
import useProjectRolePermissions from '../../../hooks/api/getters/useProjectRolePermissions/useProjectRolePermissions';
|
import useProjectRolePermissions from '../../../hooks/api/getters/useProjectRolePermissions/useProjectRolePermissions';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const CreateEnvironment = () => {
|
const CreateEnvironment = () => {
|
||||||
const { setToastApiError, setToastData } = useToast();
|
const { setToastApiError, setToastData } = useToast();
|
||||||
@ -49,8 +50,8 @@ const CreateEnvironment = () => {
|
|||||||
confetti: true,
|
confetti: true,
|
||||||
});
|
});
|
||||||
history.push('/environments');
|
history.push('/environments');
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
|||||||
import { ADMIN } from '../../providers/AccessProvider/permissions';
|
import { ADMIN } from '../../providers/AccessProvider/permissions';
|
||||||
import EnvironmentForm from '../EnvironmentForm/EnvironmentForm';
|
import EnvironmentForm from '../EnvironmentForm/EnvironmentForm';
|
||||||
import useEnvironmentForm from '../hooks/useEnvironmentForm';
|
import useEnvironmentForm from '../hooks/useEnvironmentForm';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const EditEnvironment = () => {
|
const EditEnvironment = () => {
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
@ -49,8 +50,8 @@ const EditEnvironment = () => {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
title: 'Successfully updated environment.',
|
title: 'Successfully updated environment.',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
RadioGroup,
|
|
||||||
Radio,
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import { useStyles } from './EnvironmentTypeSelector.styles';
|
import { useStyles } from './EnvironmentTypeSelector.styles';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface IEnvironmentTypeSelectorProps {
|
interface IEnvironmentTypeSelectorProps {
|
||||||
onChange: (event: React.FormEvent<HTMLInputElement>) => void;
|
onChange: (event: React.FormEvent<HTMLInputElement>) => void;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ interface IEnviromentDeleteConfirmProps {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
setSelectedEnv: React.Dispatch<React.SetStateAction<IEnvironment>>;
|
setSelectedEnv: React.Dispatch<React.SetStateAction<IEnvironment>>;
|
||||||
setDeldialogue: React.Dispatch<React.SetStateAction<boolean>>;
|
setDeldialogue: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
handleDeleteEnvironment: (name: string) => Promise<void>;
|
handleDeleteEnvironment: () => Promise<void>;
|
||||||
confirmName: string;
|
confirmName: string;
|
||||||
setConfirmName: React.Dispatch<React.SetStateAction<string>>;
|
setConfirmName: React.Dispatch<React.SetStateAction<string>>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import EnvironmentToggleConfirm from './EnvironmentToggleConfirm/EnvironmentTogg
|
|||||||
import useProjectRolePermissions from '../../../hooks/api/getters/useProjectRolePermissions/useProjectRolePermissions';
|
import useProjectRolePermissions from '../../../hooks/api/getters/useProjectRolePermissions/useProjectRolePermissions';
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const EnvironmentList = () => {
|
const EnvironmentList = () => {
|
||||||
const defaultEnv = {
|
const defaultEnv = {
|
||||||
@ -75,16 +76,16 @@ const EnvironmentList = () => {
|
|||||||
try {
|
try {
|
||||||
await sortOrderAPICall(sortOrder);
|
await sortOrderAPICall(sortOrder);
|
||||||
refetch();
|
refetch();
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const sortOrderAPICall = async (sortOrder: ISortOrderPayload) => {
|
const sortOrderAPICall = async (sortOrder: ISortOrderPayload) => {
|
||||||
try {
|
try {
|
||||||
await changeSortOrder(sortOrder);
|
await changeSortOrder(sortOrder);
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -97,8 +98,8 @@ const EnvironmentList = () => {
|
|||||||
title: 'Project environment deleted',
|
title: 'Project environment deleted',
|
||||||
text: 'You have successfully deleted the project environment.',
|
text: 'You have successfully deleted the project environment.',
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
} finally {
|
} finally {
|
||||||
setDeldialogue(false);
|
setDeldialogue(false);
|
||||||
setSelectedEnv(defaultEnv);
|
setSelectedEnv(defaultEnv);
|
||||||
@ -124,8 +125,8 @@ const EnvironmentList = () => {
|
|||||||
title: 'Project environment enabled',
|
title: 'Project environment enabled',
|
||||||
text: 'Your environment is enabled',
|
text: 'Your environment is enabled',
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
} finally {
|
} finally {
|
||||||
refetch();
|
refetch();
|
||||||
}
|
}
|
||||||
@ -140,8 +141,8 @@ const EnvironmentList = () => {
|
|||||||
title: 'Project environment disabled',
|
title: 'Project environment disabled',
|
||||||
text: 'Your environment is disabled.',
|
text: 'Your environment is disabled.',
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
} finally {
|
} finally {
|
||||||
refetch();
|
refetch();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
|||||||
import { CF_CREATE_BTN_ID } from '../../../testIds';
|
import { CF_CREATE_BTN_ID } from '../../../testIds';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import UIContext from '../../../contexts/UIContext';
|
import UIContext from '../../../contexts/UIContext';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const CreateFeature = () => {
|
const CreateFeature = () => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
@ -53,8 +54,8 @@ const CreateFeature = () => {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
setShowFeedback(true);
|
setShowFeedback(true);
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { IFeatureViewParams } from '../../../interfaces/params';
|
|||||||
import * as jsonpatch from 'fast-json-patch';
|
import * as jsonpatch from 'fast-json-patch';
|
||||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
||||||
import { UPDATE_FEATURE } from '../../providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE } from '../../providers/AccessProvider/permissions';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const EditFeature = () => {
|
const EditFeature = () => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
@ -57,8 +58,8 @@ const EditFeature = () => {
|
|||||||
title: 'Toggle updated successfully',
|
title: 'Toggle updated successfully',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import { TableCell, TableRow } from '@material-ui/core';
|
import { TableCell, TableRow } from '@material-ui/core';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
|
|
||||||
import { useStyles } from '../FeatureToggleListNew.styles';
|
import { useStyles } from '../FeatureToggleListNew.styles';
|
||||||
import useToggleFeatureByEnv from '../../../../hooks/api/actions/useToggleFeatureByEnv/useToggleFeatureByEnv';
|
import useToggleFeatureByEnv from '../../../../hooks/api/actions/useToggleFeatureByEnv/useToggleFeatureByEnv';
|
||||||
import { IEnvironments } from '../../../../interfaces/featureToggle';
|
import {
|
||||||
|
IEnvironments,
|
||||||
|
IFeatureEnvironment,
|
||||||
|
} from '../../../../interfaces/featureToggle';
|
||||||
import useToast from '../../../../hooks/useToast';
|
import useToast from '../../../../hooks/useToast';
|
||||||
import { getTogglePath } from '../../../../utils/route-path-helpers';
|
import { getTogglePath } from '../../../../utils/route-path-helpers';
|
||||||
import { SyntheticEvent } from 'react-router/node_modules/@types/react';
|
import { SyntheticEvent } from 'react-router/node_modules/@types/react';
|
||||||
@ -25,8 +27,8 @@ interface IFeatureToggleListNewItemProps {
|
|||||||
type: string;
|
type: string;
|
||||||
environments: IFeatureEnvironment[];
|
environments: IFeatureEnvironment[];
|
||||||
projectId: string;
|
projectId: string;
|
||||||
lastSeenAt?: Date;
|
lastSeenAt?: string;
|
||||||
createdAt: Date;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeatureToggleListNewItem = ({
|
const FeatureToggleListNewItem = ({
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { DialogContentText } from '@material-ui/core';
|
import { DialogContentText } from '@material-ui/core';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
import { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { IFeatureViewParams } from '../../../../../interfaces/params';
|
import { IFeatureViewParams } from '../../../../../interfaces/params';
|
||||||
import Dialogue from '../../../../common/Dialogue';
|
import Dialogue from '../../../../common/Dialogue';
|
||||||
import Input from '../../../../common/Input/Input';
|
import Input from '../../../../common/Input/Input';
|
||||||
@ -11,6 +11,7 @@ import TagSelect from '../../../../common/TagSelect/TagSelect';
|
|||||||
import useFeatureApi from '../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
import useFeatureApi from '../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||||
import useTags from '../../../../../hooks/api/getters/useTags/useTags';
|
import useTags from '../../../../../hooks/api/getters/useTags/useTags';
|
||||||
import useToast from '../../../../../hooks/useToast';
|
import useToast from '../../../../../hooks/useToast';
|
||||||
|
import { formatUnknownError } from '../../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
interface IAddTagDialogProps {
|
interface IAddTagDialogProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -20,6 +21,7 @@ interface IAddTagDialogProps {
|
|||||||
interface IDefaultTag {
|
interface IDefaultTag {
|
||||||
type: string;
|
type: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
|
||||||
[index: string]: string;
|
[index: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,9 +64,10 @@ const AddTagDialog = ({ open, setOpen }: IAddTagDialogProps) => {
|
|||||||
text: 'We successfully added a tag to your toggle',
|
text: 'We successfully added a tag to your toggle',
|
||||||
confetti: true,
|
confetti: true,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
const message = formatUnknownError(error);
|
||||||
setErrors({ tagError: e.message });
|
setToastApiError(message);
|
||||||
|
setErrors({ tagError: message });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
|||||||
import PermissionSwitch from '../../../../../common/PermissionSwitch/PermissionSwitch';
|
import PermissionSwitch from '../../../../../common/PermissionSwitch/PermissionSwitch';
|
||||||
import StringTruncator from '../../../../../common/StringTruncator/StringTruncator';
|
import StringTruncator from '../../../../../common/StringTruncator/StringTruncator';
|
||||||
import { UPDATE_FEATURE_ENVIRONMENT } from '../../../../../providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE_ENVIRONMENT } from '../../../../../providers/AccessProvider/permissions';
|
||||||
|
import React from 'react';
|
||||||
|
import { formatUnknownError } from '../../../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
interface IFeatureOverviewEnvSwitchProps {
|
interface IFeatureOverviewEnvSwitchProps {
|
||||||
env: IFeatureEnvironment;
|
env: IFeatureEnvironment;
|
||||||
@ -40,7 +42,7 @@ const FeatureOverviewEnvSwitch = ({
|
|||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
if (e.message === ENVIRONMENT_STRATEGY_ERROR) {
|
if (e.message === ENVIRONMENT_STRATEGY_ERROR) {
|
||||||
showInfoBox(true);
|
showInfoBox(true);
|
||||||
} else {
|
} else {
|
||||||
@ -61,8 +63,8 @@ const FeatureOverviewEnvSwitch = ({
|
|||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Settings } from '@material-ui/icons';
|
import { Settings } from '@material-ui/icons';
|
||||||
import { useTheme } from '@material-ui/styles';
|
import { useTheme } from '@material-ui/core/styles';
|
||||||
import { Link, useParams } from 'react-router-dom';
|
import { Link, useParams } from 'react-router-dom';
|
||||||
import { IFeatureViewParams } from '../../../../../../../../interfaces/params';
|
import { IFeatureViewParams } from '../../../../../../../../interfaces/params';
|
||||||
import { IFeatureStrategy } from '../../../../../../../../interfaces/strategy';
|
import { IFeatureStrategy } from '../../../../../../../../interfaces/strategy';
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useState, useContext } from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import { Chip } from '@material-ui/core';
|
import { Chip } from '@material-ui/core';
|
||||||
import { Label, Close } from '@material-ui/icons';
|
import { Close, Label } from '@material-ui/icons';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import useTags from '../../../../../../hooks/api/getters/useTags/useTags';
|
import useTags from '../../../../../../hooks/api/getters/useTags/useTags';
|
||||||
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
||||||
@ -17,6 +17,7 @@ import useToast from '../../../../../../hooks/useToast';
|
|||||||
import { UPDATE_FEATURE } from '../../../../../providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE } from '../../../../../providers/AccessProvider/permissions';
|
||||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||||
import AccessContext from '../../../../../../contexts/AccessContext';
|
import AccessContext from '../../../../../../contexts/AccessContext';
|
||||||
|
import { formatUnknownError } from '../../../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
interface IFeatureOverviewTagsProps extends React.HTMLProps<HTMLButtonElement> {
|
interface IFeatureOverviewTagsProps extends React.HTMLProps<HTMLButtonElement> {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@ -53,8 +54,8 @@ const FeatureOverviewTags: React.FC<IFeatureOverviewTagsProps> = ({
|
|||||||
title: 'Tag deleted',
|
title: 'Tag deleted',
|
||||||
text: 'Successfully deleted tag',
|
text: 'Successfully deleted tag',
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, useContext } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import * as jsonpatch from 'fast-json-patch';
|
import * as jsonpatch from 'fast-json-patch';
|
||||||
import { TextField } from '@material-ui/core';
|
import { TextField } from '@material-ui/core';
|
||||||
import PermissionButton from '../../../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../../../common/PermissionButton/PermissionButton';
|
||||||
@ -11,6 +11,7 @@ import { IFeatureViewParams } from '../../../../../interfaces/params';
|
|||||||
import useToast from '../../../../../hooks/useToast';
|
import useToast from '../../../../../hooks/useToast';
|
||||||
import useFeatureApi from '../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
import useFeatureApi from '../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||||
import ConditionallyRender from '../../../../common/ConditionallyRender';
|
import ConditionallyRender from '../../../../common/ConditionallyRender';
|
||||||
|
import { formatUnknownError } from '../../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const FeatureSettingsMetadata = () => {
|
const FeatureSettingsMetadata = () => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
@ -54,8 +55,8 @@ const FeatureSettingsMetadata = () => {
|
|||||||
});
|
});
|
||||||
setDirty(false);
|
setDirty(false);
|
||||||
refetch();
|
refetch();
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect, useContext } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import { useHistory, useParams } from 'react-router';
|
import { useHistory, useParams } from 'react-router';
|
||||||
import AccessContext from '../../../../../contexts/AccessContext';
|
import AccessContext from '../../../../../contexts/AccessContext';
|
||||||
import useFeatureApi from '../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
import useFeatureApi from '../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||||
@ -12,6 +12,7 @@ import FeatureProjectSelect from './FeatureProjectSelect/FeatureProjectSelect';
|
|||||||
import FeatureSettingsProjectConfirm from './FeatureSettingsProjectConfirm/FeatureSettingsProjectConfirm';
|
import FeatureSettingsProjectConfirm from './FeatureSettingsProjectConfirm/FeatureSettingsProjectConfirm';
|
||||||
import { IPermission } from '../../../../../interfaces/user';
|
import { IPermission } from '../../../../../interfaces/user';
|
||||||
import { useAuthPermissions } from '../../../../../hooks/api/getters/useAuth/useAuthPermissions';
|
import { useAuthPermissions } from '../../../../../hooks/api/getters/useAuth/useAuthPermissions';
|
||||||
|
import { formatUnknownError } from '../../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const FeatureSettingsProject = () => {
|
const FeatureSettingsProject = () => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
@ -61,16 +62,16 @@ const FeatureSettingsProject = () => {
|
|||||||
history.replace(
|
history.replace(
|
||||||
`/projects/${newProject}/features/${featureId}/settings`
|
`/projects/${newProject}/features/${featureId}/settings`
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const createMoveTargets = () => {
|
const createMoveTargets = () => {
|
||||||
return permissions.reduce(
|
return permissions.reduce(
|
||||||
(acc: { [key: string]: boolean }, permission: IPermission) => {
|
(acc: { [key: string]: boolean }, p: IPermission) => {
|
||||||
if (permission.permission === MOVE_FEATURE_TOGGLE) {
|
if (p.project && p.permission === MOVE_FEATURE_TOGGLE) {
|
||||||
acc[permission.project] = true;
|
acc[p.project] = true;
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { useStyles } from './FeatureStatus.styles';
|
import { useStyles } from './FeatureStatus.styles';
|
||||||
import TimeAgo from 'react-timeago';
|
import TimeAgo from 'react-timeago';
|
||||||
import ConditionallyRender from '../../../common/ConditionallyRender';
|
import ConditionallyRender from '../../../common/ConditionallyRender';
|
||||||
import { Tooltip } from '@material-ui/core';
|
import { Tooltip, TooltipProps } from '@material-ui/core';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
function generateUnit(unit?: string): string {
|
function generateUnit(unit?: string): string {
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
@ -46,8 +47,8 @@ function getColor(unit?: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface FeatureStatusProps {
|
interface FeatureStatusProps {
|
||||||
lastSeenAt?: Date;
|
lastSeenAt?: string;
|
||||||
tooltipPlacement?: string;
|
tooltipPlacement?: TooltipProps['placement'];
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeatureStatus = ({
|
const FeatureStatus = ({
|
||||||
@ -76,7 +77,7 @@ const FeatureStatus = ({
|
|||||||
condition={!!lastSeenAt}
|
condition={!!lastSeenAt}
|
||||||
show={
|
show={
|
||||||
<TimeAgo
|
<TimeAgo
|
||||||
date={lastSeenAt}
|
date={lastSeenAt!}
|
||||||
title=""
|
title=""
|
||||||
live={false}
|
live={false}
|
||||||
formatter={(
|
formatter={(
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import { ADD_NEW_STRATEGY_SAVE_ID } from '../../../../../../testIds';
|
|||||||
import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature';
|
import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature';
|
||||||
import { scrollToTop } from '../../../../../common/util';
|
import { scrollToTop } from '../../../../../common/util';
|
||||||
import useToast from '../../../../../../hooks/useToast';
|
import useToast from '../../../../../../hooks/useToast';
|
||||||
|
import { formatUnknownError } from '../../../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const FeatureStrategiesConfigure = () => {
|
const FeatureStrategiesConfigure = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@ -99,8 +100,8 @@ const FeatureStrategiesConfigure = () => {
|
|||||||
history.replace(history.location.pathname);
|
history.replace(history.location.pathname);
|
||||||
refetch();
|
refetch();
|
||||||
scrollToTop();
|
scrollToTop();
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,6 @@ const FeatureStrategiesEnvironmentList = ({
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
activeEnvironmentsRef,
|
activeEnvironmentsRef,
|
||||||
setToastData,
|
|
||||||
deleteStrategy,
|
deleteStrategy,
|
||||||
updateStrategy,
|
updateStrategy,
|
||||||
delDialog,
|
delDialog,
|
||||||
@ -162,7 +161,6 @@ const FeatureStrategiesEnvironmentList = ({
|
|||||||
: 'Toggle is disabled and no strategies are executing'
|
: 'Toggle is disabled and no strategies are executing'
|
||||||
}
|
}
|
||||||
env={activeEnvironment}
|
env={activeEnvironment}
|
||||||
setToastData={setToastData}
|
|
||||||
callback={updateFeatureEnvironmentCache}
|
callback={updateFeatureEnvironmentCache}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,9 +4,13 @@ import FeatureStrategiesUIContext from '../../../../../../contexts/FeatureStrate
|
|||||||
import useFeatureStrategyApi from '../../../../../../hooks/api/actions/useFeatureStrategyApi/useFeatureStrategyApi';
|
import useFeatureStrategyApi from '../../../../../../hooks/api/actions/useFeatureStrategyApi/useFeatureStrategyApi';
|
||||||
import useToast from '../../../../../../hooks/useToast';
|
import useToast from '../../../../../../hooks/useToast';
|
||||||
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
||||||
import { IFeatureStrategy } from '../../../../../../interfaces/strategy';
|
import {
|
||||||
|
IFeatureStrategy,
|
||||||
|
IStrategyPayload,
|
||||||
|
} from '../../../../../../interfaces/strategy';
|
||||||
import cloneDeep from 'lodash.clonedeep';
|
import cloneDeep from 'lodash.clonedeep';
|
||||||
import { IFeatureEnvironment } from '../../../../../../interfaces/featureToggle';
|
import { IFeatureEnvironment } from '../../../../../../interfaces/featureToggle';
|
||||||
|
import { formatUnknownError } from '../../../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const useFeatureStrategiesEnvironmentList = () => {
|
const useFeatureStrategiesEnvironmentList = () => {
|
||||||
const { projectId, featureId } = useParams<IFeatureViewParams>();
|
const { projectId, featureId } = useParams<IFeatureViewParams>();
|
||||||
@ -85,8 +89,8 @@ const useFeatureStrategiesEnvironmentList = () => {
|
|||||||
strategy.constraints = updateStrategyPayload.constraints;
|
strategy.constraints = updateStrategyPayload.constraints;
|
||||||
history.replace(history.location.pathname);
|
history.replace(history.location.pathname);
|
||||||
setFeatureCache(feature);
|
setFeatureCache(feature);
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -118,14 +122,13 @@ const useFeatureStrategiesEnvironmentList = () => {
|
|||||||
text: `Successfully deleted strategy from ${featureId}`,
|
text: `Successfully deleted strategy from ${featureId}`,
|
||||||
});
|
});
|
||||||
history.replace(history.location.pathname);
|
history.replace(history.location.pathname);
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
activeEnvironmentsRef,
|
activeEnvironmentsRef,
|
||||||
setToastData,
|
|
||||||
deleteStrategy,
|
deleteStrategy,
|
||||||
updateStrategy,
|
updateStrategy,
|
||||||
delDialog,
|
delDialog,
|
||||||
|
|||||||
@ -11,7 +11,7 @@ interface IFeatureStrategiesProductionGuard {
|
|||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
primaryButtonText: string;
|
primaryButtonText: string;
|
||||||
loading: boolean;
|
loading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeatureStrategiesProductionGuard = ({
|
const FeatureStrategiesProductionGuard = ({
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useContext, useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { mutate } from 'swr';
|
import { mutate } from 'swr';
|
||||||
import FeatureStrategiesUIContext from '../../../../../../contexts/FeatureStrategiesUIContext';
|
import FeatureStrategiesUIContext from '../../../../../../contexts/FeatureStrategiesUIContext';
|
||||||
@ -6,8 +6,8 @@ import useFeatureStrategy from '../../../../../../hooks/api/getters/useFeatureSt
|
|||||||
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
||||||
import {
|
import {
|
||||||
IConstraint,
|
IConstraint,
|
||||||
IParameter,
|
|
||||||
IFeatureStrategy,
|
IFeatureStrategy,
|
||||||
|
IParameter,
|
||||||
} from '../../../../../../interfaces/strategy';
|
} from '../../../../../../interfaces/strategy';
|
||||||
import FeatureStrategyAccordion from '../../FeatureStrategyAccordion/FeatureStrategyAccordion';
|
import FeatureStrategyAccordion from '../../FeatureStrategyAccordion/FeatureStrategyAccordion';
|
||||||
import cloneDeep from 'lodash.clonedeep';
|
import cloneDeep from 'lodash.clonedeep';
|
||||||
|
|||||||
@ -23,7 +23,7 @@ interface IFeatureStrategyCardProps {
|
|||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
configureNewStrategy: boolean;
|
configureNewStrategy: boolean;
|
||||||
index?: number;
|
index: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FEATURE_STRATEGIES_DRAG_TYPE = 'FEATURE_STRATEGIES_DRAG_TYPE';
|
export const FEATURE_STRATEGIES_DRAG_TYPE = 'FEATURE_STRATEGIES_DRAG_TYPE';
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import useStrategies from '../../../../../../hooks/api/getters/useStrategies/use
|
|||||||
import GeneralStrategy from '../../common/GeneralStrategy/GeneralStrategy';
|
import GeneralStrategy from '../../common/GeneralStrategy/GeneralStrategy';
|
||||||
import UserWithIdStrategy from '../../common/UserWithIdStrategy/UserWithId';
|
import UserWithIdStrategy from '../../common/UserWithIdStrategy/UserWithId';
|
||||||
import StrategyConstraints from '../../common/StrategyConstraints/StrategyConstraints';
|
import StrategyConstraints from '../../common/StrategyConstraints/StrategyConstraints';
|
||||||
import { useContext, useState } from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||||
import useUiConfig from '../../../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from '../../../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { C } from '../../../../../common/flags';
|
import { C } from '../../../../../common/flags';
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
Switch,
|
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Tooltip,
|
Switch,
|
||||||
TextField,
|
TextField,
|
||||||
|
Tooltip,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
|
|
||||||
import StrategyInputList from '../StrategyInputList/StrategyInputList';
|
import StrategyInputList from '../StrategyInputList/StrategyInputList';
|
||||||
import RolloutSlider from '../RolloutSlider/RolloutSlider';
|
import RolloutSlider from '../RolloutSlider/RolloutSlider';
|
||||||
import {
|
import {
|
||||||
IParameter,
|
|
||||||
IFeatureStrategy,
|
IFeatureStrategy,
|
||||||
|
IParameter,
|
||||||
} from '../../../../../../interfaces/strategy';
|
} from '../../../../../../interfaces/strategy';
|
||||||
import { useStyles } from './GeneralStrategy.styles';
|
import { useStyles } from './GeneralStrategy.styles';
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ const GeneralStrategy = ({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (type === 'list') {
|
} else if (type === 'list') {
|
||||||
let list = [];
|
let list: string[] = [];
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
list = value.trim().split(',').filter(Boolean);
|
list = value.trim().split(',').filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { makeStyles, withStyles } from '@material-ui/core/styles';
|
import { makeStyles, withStyles } from '@material-ui/core/styles';
|
||||||
import { Slider, Typography } from '@material-ui/core';
|
import { Slider, Typography } from '@material-ui/core';
|
||||||
import { ROLLOUT_SLIDER_ID } from '../../../../../../testIds';
|
import { ROLLOUT_SLIDER_ID } from '../../../../../../testIds';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
const StyledSlider = withStyles({
|
const StyledSlider = withStyles({
|
||||||
root: {
|
root: {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import useUiConfig from '../../../../../../hooks/api/getters/useUiConfig/useUiCo
|
|||||||
import { C } from '../../../../../common/flags';
|
import { C } from '../../../../../common/flags';
|
||||||
import useUnleashContext from '../../../../../../hooks/api/getters/useUnleashContext/useUnleashContext';
|
import useUnleashContext from '../../../../../../hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||||
import StrategyConstraintInputField from './StrategyConstraintInputField';
|
import StrategyConstraintInputField from './StrategyConstraintInputField';
|
||||||
import { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
interface IStrategyConstraintProps {
|
interface IStrategyConstraintProps {
|
||||||
constraints: IConstraint[];
|
constraints: IConstraint[];
|
||||||
@ -38,7 +38,7 @@ const StrategyConstraints: React.FC<IStrategyConstraintProps> = ({
|
|||||||
const enabled = uiConfig.flags[C];
|
const enabled = uiConfig.flags[C];
|
||||||
const contextNames = contextFields.map(context => context.name);
|
const contextNames = contextFields.map(context => context.name);
|
||||||
|
|
||||||
const onClick = evt => {
|
const onClick = (evt: React.SyntheticEvent) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
addConstraint();
|
addConstraint();
|
||||||
};
|
};
|
||||||
@ -57,15 +57,15 @@ const StrategyConstraints: React.FC<IStrategyConstraintProps> = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeConstraint = index => evt => {
|
const removeConstraint = (index: number) => (event: Event) => {
|
||||||
evt.preventDefault();
|
event.preventDefault();
|
||||||
const updatedConstraints = [...constraints];
|
const updatedConstraints = [...constraints];
|
||||||
updatedConstraints.splice(index, 1);
|
updatedConstraints.splice(index, 1);
|
||||||
|
|
||||||
updateConstraints(updatedConstraints);
|
updateConstraints(updatedConstraints);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateConstraint = index => (value, field) => {
|
const updateConstraint = (index: number) => (value, field) => {
|
||||||
const updatedConstraints = [...constraints];
|
const updatedConstraints = [...constraints];
|
||||||
const constraint = updatedConstraints[index];
|
const constraint = updatedConstraints[index];
|
||||||
constraint[field] = value;
|
constraint[field] = value;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
interface IStrategyInputList {
|
interface IStrategyInputList {
|
||||||
name: string;
|
name: string;
|
||||||
list: string[];
|
list: string[];
|
||||||
setConfig: () => void;
|
setConfig: (field: string, value: string) => void;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import StrategyInputList from '../StrategyInputList/StrategyInputList';
|
|||||||
|
|
||||||
interface IUserWithIdStrategyProps {
|
interface IUserWithIdStrategyProps {
|
||||||
parameters: IParameter;
|
parameters: IParameter;
|
||||||
updateParameter: (field: string, value: any) => void;
|
updateParameter: (field: string, value: string) => void;
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
FormControl,
|
FormControl,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Grid,
|
Grid,
|
||||||
TextField,
|
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
Button,
|
TextField,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import { Info } from '@material-ui/icons';
|
import { Info } from '@material-ui/icons';
|
||||||
@ -18,13 +17,16 @@ import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
|||||||
import GeneralSelect from '../../../../../common/GeneralSelect/GeneralSelect';
|
import GeneralSelect from '../../../../../common/GeneralSelect/GeneralSelect';
|
||||||
import { useCommonStyles } from '../../../../../../common.styles';
|
import { useCommonStyles } from '../../../../../../common.styles';
|
||||||
import Dialogue from '../../../../../common/Dialogue';
|
import Dialogue from '../../../../../common/Dialogue';
|
||||||
import { trim, modalStyles } from '../../../../../common/util';
|
import { modalStyles, trim } from '../../../../../common/util';
|
||||||
import PermissionSwitch from '../../../../../common/PermissionSwitch/PermissionSwitch';
|
import PermissionSwitch from '../../../../../common/PermissionSwitch/PermissionSwitch';
|
||||||
import { UPDATE_FEATURE_VARIANTS } from '../../../../../providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE_VARIANTS } from '../../../../../providers/AccessProvider/permissions';
|
||||||
import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature';
|
import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
||||||
import { IFeatureVariant } from '../../../../../../interfaces/featureToggle';
|
import {
|
||||||
|
IFeatureVariant,
|
||||||
|
IOverride,
|
||||||
|
} from '../../../../../../interfaces/featureToggle';
|
||||||
import cloneDeep from 'lodash.clonedeep';
|
import cloneDeep from 'lodash.clonedeep';
|
||||||
|
|
||||||
const payloadOptions = [
|
const payloadOptions = [
|
||||||
@ -35,6 +37,17 @@ const payloadOptions = [
|
|||||||
|
|
||||||
const EMPTY_PAYLOAD = { type: 'string', value: '' };
|
const EMPTY_PAYLOAD = { type: 'string', value: '' };
|
||||||
|
|
||||||
|
interface IAddVariantProps {
|
||||||
|
showDialog: boolean;
|
||||||
|
closeDialog: () => void;
|
||||||
|
save: (variantToSave: IFeatureVariant) => Promise<void>;
|
||||||
|
editVariant: IFeatureVariant;
|
||||||
|
validateName: (value: string) => Record<string, string> | undefined;
|
||||||
|
validateWeight: (value: string) => Record<string, string> | undefined;
|
||||||
|
title: string;
|
||||||
|
editing: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
const AddVariant = ({
|
const AddVariant = ({
|
||||||
showDialog,
|
showDialog,
|
||||||
closeDialog,
|
closeDialog,
|
||||||
@ -44,11 +57,11 @@ const AddVariant = ({
|
|||||||
validateWeight,
|
validateWeight,
|
||||||
title,
|
title,
|
||||||
editing,
|
editing,
|
||||||
}) => {
|
}: IAddVariantProps) => {
|
||||||
const [data, setData] = useState({});
|
const [data, setData] = useState({});
|
||||||
const [payload, setPayload] = useState(EMPTY_PAYLOAD);
|
const [payload, setPayload] = useState(EMPTY_PAYLOAD);
|
||||||
const [overrides, setOverrides] = useState([]);
|
const [overrides, setOverrides] = useState<IOverride[]>([]);
|
||||||
const [error, setError] = useState({});
|
const [error, setError] = useState<Record<string, string>>({});
|
||||||
const commonStyles = useCommonStyles();
|
const commonStyles = useCommonStyles();
|
||||||
const { projectId, featureId } = useParams<IFeatureViewParams>();
|
const { projectId, featureId } = useParams<IFeatureViewParams>();
|
||||||
const { feature } = useFeature(projectId, featureId);
|
const { feature } = useFeature(projectId, featureId);
|
||||||
@ -80,7 +93,7 @@ const AddVariant = ({
|
|||||||
setError({});
|
setError({});
|
||||||
};
|
};
|
||||||
|
|
||||||
const setClonedVariants = clonedVariants =>
|
const setClonedVariants = (clonedVariants: IFeatureVariant[]) =>
|
||||||
setVariants(cloneDeep(clonedVariants));
|
setVariants(cloneDeep(clonedVariants));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -159,7 +172,7 @@ const AddVariant = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPayload = e => {
|
const onPayload = (e: React.SyntheticEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setPayload({
|
setPayload({
|
||||||
...payload,
|
...payload,
|
||||||
@ -167,13 +180,13 @@ const AddVariant = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCancel = e => {
|
const onCancel = (e: React.SyntheticEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
clear();
|
clear();
|
||||||
closeDialog();
|
closeDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateOverrideType = index => e => {
|
const updateOverrideType = (index: number) => (e: React.SyntheticEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setOverrides(
|
setOverrides(
|
||||||
overrides.map((o, i) => {
|
overrides.map((o, i) => {
|
||||||
@ -186,7 +199,7 @@ const AddVariant = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateOverrideValues = (index, values) => {
|
const updateOverrideValues = (index: number, values: string[]) => {
|
||||||
setOverrides(
|
setOverrides(
|
||||||
overrides.map((o, i) => {
|
overrides.map((o, i) => {
|
||||||
if (i === index) {
|
if (i === index) {
|
||||||
@ -197,12 +210,12 @@ const AddVariant = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeOverride = index => e => {
|
const removeOverride = (index: number) => (e: React.SyntheticEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setOverrides(overrides.filter((o, i) => i !== index));
|
setOverrides(overrides.filter((o, i) => i !== index));
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAddOverride = e => {
|
const onAddOverride = (e: React.SyntheticEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setOverrides([
|
setOverrides([
|
||||||
...overrides,
|
...overrides,
|
||||||
@ -388,7 +401,6 @@ const AddVariant = ({
|
|||||||
removeOverride={removeOverride}
|
removeOverride={removeOverride}
|
||||||
updateOverrideType={updateOverrideType}
|
updateOverrideType={updateOverrideType}
|
||||||
updateOverrideValues={updateOverrideValues}
|
updateOverrideValues={updateOverrideValues}
|
||||||
updateValues={updateOverrideValues}
|
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
onClick={onAddOverride}
|
onClick={onAddOverride}
|
||||||
@ -402,15 +414,4 @@ const AddVariant = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
AddVariant.propTypes = {
|
|
||||||
showDialog: PropTypes.bool.isRequired,
|
|
||||||
closeDialog: PropTypes.func.isRequired,
|
|
||||||
save: PropTypes.func.isRequired,
|
|
||||||
validateName: PropTypes.func.isRequired,
|
|
||||||
validateWeight: PropTypes.func.isRequired,
|
|
||||||
editVariant: PropTypes.object,
|
|
||||||
title: PropTypes.string,
|
|
||||||
uiConfig: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AddVariant;
|
export default AddVariant;
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import cloneDeep from 'lodash.clonedeep';
|
|||||||
import useDeleteVariantMarkup from './FeatureVariantsListItem/useDeleteVariantMarkup';
|
import useDeleteVariantMarkup from './FeatureVariantsListItem/useDeleteVariantMarkup';
|
||||||
import PermissionButton from '../../../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../../../common/PermissionButton/PermissionButton';
|
||||||
import { mutate } from 'swr';
|
import { mutate } from 'swr';
|
||||||
|
import { formatUnknownError } from '../../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const FeatureOverviewVariants = () => {
|
const FeatureOverviewVariants = () => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
@ -155,8 +156,8 @@ const FeatureOverviewVariants = () => {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
text: 'Successfully updated variant stickiness',
|
text: 'Successfully updated variant stickiness',
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -167,8 +168,8 @@ const FeatureOverviewVariants = () => {
|
|||||||
updatedVariants,
|
updatedVariants,
|
||||||
'Successfully removed variant'
|
'Successfully removed variant'
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const updateVariant = async (variant: IFeatureVariant) => {
|
const updateVariant = async (variant: IFeatureVariant) => {
|
||||||
@ -210,8 +211,8 @@ const FeatureOverviewVariants = () => {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
text: successText,
|
text: successText,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.message);
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -221,7 +222,7 @@ const FeatureOverviewVariants = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateWeight = (weight: number) => {
|
const validateWeight = (weight: string) => {
|
||||||
const weightValue = parseInt(weight);
|
const weightValue = parseInt(weight);
|
||||||
if (weightValue > 100 || weightValue < 0) {
|
if (weightValue > 100 || weightValue < 0) {
|
||||||
return { weight: 'weight must be between 0 and 100' };
|
return { weight: 'weight must be between 0 and 100' };
|
||||||
@ -230,7 +231,7 @@ const FeatureOverviewVariants = () => {
|
|||||||
|
|
||||||
const delDialogueMarkup = useDeleteVariantMarkup({
|
const delDialogueMarkup = useDeleteVariantMarkup({
|
||||||
show: delDialog.show,
|
show: delDialog.show,
|
||||||
onClick: e => {
|
onClick: () => {
|
||||||
removeVariant(delDialog.name);
|
removeVariant(delDialog.name);
|
||||||
setDelDialog({ name: '', show: false });
|
setDelDialog({ name: '', show: false });
|
||||||
setToastData({
|
setToastData({
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { IconButton, Chip, TableCell, TableRow } from '@material-ui/core';
|
import { Chip, IconButton, TableCell, TableRow } from '@material-ui/core';
|
||||||
import { Edit, Delete } from '@material-ui/icons';
|
import { Delete, Edit } from '@material-ui/icons';
|
||||||
|
|
||||||
import styles from '../variants.module.scss';
|
import styles from '../variants.module.scss';
|
||||||
import { IFeatureVariant } from '../../../../../../interfaces/featureToggle';
|
import { IFeatureVariant } from '../../../../../../interfaces/featureToggle';
|
||||||
@ -26,7 +26,7 @@ const FeatureVariantListItem = ({
|
|||||||
<TableCell data-test={'VARIANT_NAME'}>{variant.name}</TableCell>
|
<TableCell data-test={'VARIANT_NAME'}>{variant.name}</TableCell>
|
||||||
<TableCell className={styles.chipContainer}>
|
<TableCell className={styles.chipContainer}>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={variant.payload}
|
condition={Boolean(variant.payload)}
|
||||||
show={<Chip label="Payload" />}
|
show={<Chip label="Payload" />}
|
||||||
/>
|
/>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
|
|||||||
@ -61,7 +61,7 @@ const FeatureView = () => {
|
|||||||
setShowDelDialog(false);
|
setShowDelDialog(false);
|
||||||
projectRefetch();
|
projectRefetch();
|
||||||
history.push(`/projects/${projectId}`);
|
history.push(`/projects/${projectId}`);
|
||||||
} catch (error) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(formatUnknownError(error));
|
setToastApiError(formatUnknownError(error));
|
||||||
setShowDelDialog(false);
|
setShowDelDialog(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,9 +11,7 @@ interface IRedirectParams {
|
|||||||
const RedirectFeatureView = () => {
|
const RedirectFeatureView = () => {
|
||||||
const { name } = useParams<IRedirectParams>();
|
const { name } = useParams<IRedirectParams>();
|
||||||
const { features } = useFeatures();
|
const { features } = useFeatures();
|
||||||
const [featureToggle, setFeatureToggle] = useState<IFeatureToggle | null>(
|
const [featureToggle, setFeatureToggle] = useState<IFeatureToggle>();
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const toggle = features.find(
|
const toggle = features.find(
|
||||||
@ -23,7 +21,9 @@ const RedirectFeatureView = () => {
|
|||||||
setFeatureToggle(toggle);
|
setFeatureToggle(toggle);
|
||||||
}, [features, name]);
|
}, [features, name]);
|
||||||
|
|
||||||
if (!featureToggle) return null;
|
if (!featureToggle) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Redirect
|
<Redirect
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import useToast from '../../../../hooks/useToast';
|
|||||||
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
||||||
import { CREATE_PROJECT } from '../../../providers/AccessProvider/permissions';
|
import { CREATE_PROJECT } from '../../../providers/AccessProvider/permissions';
|
||||||
import { useAuthUser } from '../../../../hooks/api/getters/useAuth/useAuthUser';
|
import { useAuthUser } from '../../../../hooks/api/getters/useAuth/useAuthUser';
|
||||||
|
import { formatUnknownError } from '../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const CreateProject = () => {
|
const CreateProject = () => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
@ -48,8 +49,8 @@ const CreateProject = () => {
|
|||||||
confetti: true,
|
confetti: true,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
|||||||
import useToast from '../../../../hooks/useToast';
|
import useToast from '../../../../hooks/useToast';
|
||||||
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
||||||
import { UPDATE_PROJECT } from '../../../providers/AccessProvider/permissions';
|
import { UPDATE_PROJECT } from '../../../providers/AccessProvider/permissions';
|
||||||
|
import { formatUnknownError } from '../../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const EditProject = () => {
|
const EditProject = () => {
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
@ -58,8 +59,8 @@ const EditProject = () => {
|
|||||||
title: 'Project information updated',
|
title: 'Project information updated',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -45,7 +45,7 @@ const Project = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Access',
|
title: 'Access',
|
||||||
component: <ProjectAccess projectId={id} />,
|
component: <ProjectAccess />,
|
||||||
path: `${basePath}/access`,
|
path: `${basePath}/access`,
|
||||||
name: 'access',
|
name: 'access',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const ProjectFeatureToggles = ({
|
|||||||
loading,
|
loading,
|
||||||
}: IProjectFeatureToggles) => {
|
}: IProjectFeatureToggles) => {
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const { id } = useParams();
|
const { id } = useParams<{ id: string }>();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
|
|||||||
@ -38,7 +38,6 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
position: 'relative',
|
position: 'relative',
|
||||||
},
|
},
|
||||||
errorMessage: {
|
errorMessage: {
|
||||||
// @ts-expect-error
|
|
||||||
fontSize: theme.fontSizes.smallBody,
|
fontSize: theme.fontSizes.smallBody,
|
||||||
color: theme.palette.error.main,
|
color: theme.palette.error.main,
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
IProjectAccessUser,
|
IProjectAccessUser,
|
||||||
} from '../../../../hooks/api/getters/useProjectAccess/useProjectAccess';
|
} from '../../../../hooks/api/getters/useProjectAccess/useProjectAccess';
|
||||||
import { ProjectAccessListItem } from './ProjectAccessListItem/ProjectAccessListItem';
|
import { ProjectAccessListItem } from './ProjectAccessListItem/ProjectAccessListItem';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface IProjectAccesListProps {
|
interface IProjectAccesListProps {
|
||||||
page: IProjectAccessUser[];
|
page: IProjectAccessUser[];
|
||||||
|
|||||||
@ -1,22 +1,23 @@
|
|||||||
import {
|
import {
|
||||||
|
Avatar,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
Avatar,
|
|
||||||
ListItemText,
|
|
||||||
ListItemSecondaryAction,
|
ListItemSecondaryAction,
|
||||||
|
ListItemText,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import { Delete } from '@material-ui/icons';
|
import { Delete } from '@material-ui/icons';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
IProjectAccessUser,
|
|
||||||
IProjectAccessOutput,
|
IProjectAccessOutput,
|
||||||
|
IProjectAccessUser,
|
||||||
} from '../../../../../hooks/api/getters/useProjectAccess/useProjectAccess';
|
} from '../../../../../hooks/api/getters/useProjectAccess/useProjectAccess';
|
||||||
import { IProjectViewParams } from '../../../../../interfaces/params';
|
import { IProjectViewParams } from '../../../../../interfaces/params';
|
||||||
import PermissionIconButton from '../../../../common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from '../../../../common/PermissionIconButton/PermissionIconButton';
|
||||||
import { UPDATE_PROJECT } from '../../../../providers/AccessProvider/permissions';
|
import { UPDATE_PROJECT } from '../../../../providers/AccessProvider/permissions';
|
||||||
import { ProjectRoleSelect } from '../../ProjectRoleSelect/ProjectRoleSelect';
|
import { ProjectRoleSelect } from '../../ProjectRoleSelect/ProjectRoleSelect';
|
||||||
import { useStyles } from '../ProjectAccessListItem/ProjectAccessListItem.styles';
|
import { useStyles } from '../ProjectAccessListItem/ProjectAccessListItem.styles';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
interface IProjectAccessListItemProps {
|
interface IProjectAccessListItemProps {
|
||||||
user: IProjectAccessUser;
|
user: IProjectAccessUser;
|
||||||
|
|||||||
@ -2,11 +2,11 @@ import { Alert } from '@material-ui/lab';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Dialogue from '../../../common/Dialogue';
|
import Dialogue from '../../../common/Dialogue';
|
||||||
import Input from '../../../common/Input/Input';
|
import Input from '../../../common/Input/Input';
|
||||||
import { ProjectEnvironment } from '../ProjectEnvironment';
|
|
||||||
import { useStyles } from './EnvironmentDisableConfirm.styles';
|
import { useStyles } from './EnvironmentDisableConfirm.styles';
|
||||||
|
import { IProjectEnvironment } from '../../../../interfaces/environments';
|
||||||
|
|
||||||
interface IEnvironmentDisableConfirmProps {
|
interface IEnvironmentDisableConfirmProps {
|
||||||
env?: ProjectEnvironment;
|
env?: IProjectEnvironment;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
handleDisableEnvironment: () => Promise<void>;
|
handleDisableEnvironment: () => Promise<void>;
|
||||||
handleCancelDisableEnvironment: () => void;
|
handleCancelDisableEnvironment: () => void;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||||
import { useStyles } from './ProjectEnvironment.styles';
|
import { useStyles } from './ProjectEnvironment.styles';
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ interface ProjectEnvironmentListProps {
|
|||||||
|
|
||||||
const ProjectEnvironmentList = ({ projectId }: ProjectEnvironmentListProps) => {
|
const ProjectEnvironmentList = ({ projectId }: ProjectEnvironmentListProps) => {
|
||||||
// api state
|
// api state
|
||||||
const [envs, setEnvs] = useState<IProjectEnvironment>([]);
|
const [envs, setEnvs] = useState<IProjectEnvironment[]>([]);
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const {
|
const {
|
||||||
@ -76,7 +76,7 @@ const ProjectEnvironmentList = ({ projectId }: ProjectEnvironmentListProps) => {
|
|||||||
} the environment.`;
|
} the environment.`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleEnv = async (env: ProjectEnvironment) => {
|
const toggleEnv = async (env: IProjectEnvironment) => {
|
||||||
if (env.enabled) {
|
if (env.enabled) {
|
||||||
const enabledEnvs = getEnabledEnvs(envs);
|
const enabledEnvs = getEnabledEnvs(envs);
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ const ProjectEnvironmentList = ({ projectId }: ProjectEnvironmentListProps) => {
|
|||||||
setConfirmName('');
|
setConfirmName('');
|
||||||
};
|
};
|
||||||
|
|
||||||
const genLabel = (env: ProjectEnvironment) => (
|
const genLabel = (env: IProjectEnvironment) => (
|
||||||
<>
|
<>
|
||||||
<code>{env.name}</code> environment is{' '}
|
<code>{env.name}</code> environment is{' '}
|
||||||
<strong>{env.enabled ? 'enabled' : 'disabled'}</strong>
|
<strong>{env.enabled ? 'enabled' : 'disabled'}</strong>
|
||||||
|
|||||||
@ -1,17 +1,10 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import UIContext, { createEmptyToast } from '../../../contexts/UIContext';
|
||||||
import UIContext, { IToastData } from '../../../contexts/UIContext';
|
import { IToast } from '../../../interfaces/toast';
|
||||||
|
|
||||||
const UIProvider: React.FC = ({ children }) => {
|
const UIProvider: React.FC = ({ children }) => {
|
||||||
const [toastData, setToast] = useState<IToastData>({
|
const [toastData, setToast] = useState<IToast>(createEmptyToast());
|
||||||
title: '',
|
const [showFeedback, setShowFeedback] = useState(false);
|
||||||
text: '',
|
|
||||||
components: [],
|
|
||||||
show: false,
|
|
||||||
persist: false,
|
|
||||||
type: '',
|
|
||||||
});
|
|
||||||
const [showFeedback, setShowFeedback] = useState();
|
|
||||||
|
|
||||||
const context = React.useMemo(
|
const context = React.useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(theme => ({
|
export const useStyles = makeStyles(theme => ({
|
||||||
listItem: {
|
listItem: {
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import useStrategies from '../../../hooks/api/getters/useStrategies/useStrategie
|
|||||||
import useStrategiesApi from '../../../hooks/api/actions/useStrategiesApi/useStrategiesApi';
|
import useStrategiesApi from '../../../hooks/api/actions/useStrategiesApi/useStrategiesApi';
|
||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
import { IStrategy } from '../../../interfaces/strategy';
|
import { IStrategy } from '../../../interfaces/strategy';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
interface IDialogueMetaData {
|
interface IDialogueMetaData {
|
||||||
show: boolean;
|
show: boolean;
|
||||||
@ -49,7 +50,11 @@ export const StrategiesList = () => {
|
|||||||
const smallScreen = useMediaQuery('(max-width:700px)');
|
const smallScreen = useMediaQuery('(max-width:700px)');
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
const [dialogueMetaData, setDialogueMetaData] = useState<IDialogueMetaData>(
|
const [dialogueMetaData, setDialogueMetaData] = useState<IDialogueMetaData>(
|
||||||
{ show: false, title: '', onConfirm: () => {} }
|
{
|
||||||
|
show: false,
|
||||||
|
title: '',
|
||||||
|
onConfirm: () => {},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
const { strategies, refetchStrategies } = useStrategies();
|
const { strategies, refetchStrategies } = useStrategies();
|
||||||
const { removeStrategy, deprecateStrategy, reactivateStrategy } =
|
const { removeStrategy, deprecateStrategy, reactivateStrategy } =
|
||||||
@ -88,7 +93,7 @@ export const StrategiesList = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const strategyLink = ({ name, deprecated }) => (
|
const strategyLink = ({ name, deprecated }: IStrategy) => (
|
||||||
<Link to={`/strategies/view/${name}`}>
|
<Link to={`/strategies/view/${name}`}>
|
||||||
<strong>{getHumanReadableStrategyName(name)}</strong>
|
<strong>{getHumanReadableStrategyName(name)}</strong>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
@ -111,8 +116,8 @@ export const StrategiesList = () => {
|
|||||||
title: 'Success',
|
title: 'Success',
|
||||||
text: 'Strategy reactivated successfully',
|
text: 'Strategy reactivated successfully',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -131,8 +136,8 @@ export const StrategiesList = () => {
|
|||||||
title: 'Success',
|
title: 'Success',
|
||||||
text: 'Strategy deprecated successfully',
|
text: 'Strategy deprecated successfully',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -151,8 +156,8 @@ export const StrategiesList = () => {
|
|||||||
title: 'Success',
|
title: 'Success',
|
||||||
text: 'Strategy deleted successfully',
|
text: 'Strategy deleted successfully',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export const StrategyView = () => {
|
|||||||
const { applications } = useApplications();
|
const { applications } = useApplications();
|
||||||
|
|
||||||
const toggles = features.filter(toggle => {
|
const toggles = features.filter(toggle => {
|
||||||
return toggle?.strategies.findIndex(s => s.name === strategyName) > -1;
|
return toggle?.strategies?.find(s => s.name === strategyName);
|
||||||
});
|
});
|
||||||
|
|
||||||
const strategy = strategies.find(n => n.name === strategyName);
|
const strategy = strategies.find(n => n.name === strategyName);
|
||||||
|
|||||||
@ -5,13 +5,14 @@ import {
|
|||||||
ListItemText,
|
ListItemText,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import { PlayArrow, Pause } from '@material-ui/icons';
|
import { Pause, PlayArrow } from '@material-ui/icons';
|
||||||
import styles from '../../common/common.module.scss';
|
import styles from '../../common/common.module.scss';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||||
|
import { IFeatureToggle } from '../../../interfaces/featureToggle';
|
||||||
|
|
||||||
interface ITogglesLinkListProps {
|
interface ITogglesLinkListProps {
|
||||||
toggles: [];
|
toggles: IFeatureToggle[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TogglesLinkList = ({ toggles }: ITogglesLinkListProps) => (
|
export const TogglesLinkList = ({ toggles }: ITogglesLinkListProps) => (
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
|||||||
import { UPDATE_TAG_TYPE } from '../../providers/AccessProvider/permissions';
|
import { UPDATE_TAG_TYPE } from '../../providers/AccessProvider/permissions';
|
||||||
import useTagTypeForm from '../TagTypeForm/useTagTypeForm';
|
import useTagTypeForm from '../TagTypeForm/useTagTypeForm';
|
||||||
import TagTypeForm from '../TagTypeForm/TagTypeForm';
|
import TagTypeForm from '../TagTypeForm/TagTypeForm';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const CreateTagType = () => {
|
const CreateTagType = () => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
@ -38,8 +39,8 @@ const CreateTagType = () => {
|
|||||||
confetti: true,
|
confetti: true,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
|||||||
import { UPDATE_TAG_TYPE } from '../../providers/AccessProvider/permissions';
|
import { UPDATE_TAG_TYPE } from '../../providers/AccessProvider/permissions';
|
||||||
import useTagTypeForm from '../TagTypeForm/useTagTypeForm';
|
import useTagTypeForm from '../TagTypeForm/useTagTypeForm';
|
||||||
import TagForm from '../TagTypeForm/TagTypeForm';
|
import TagForm from '../TagTypeForm/TagTypeForm';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const EditTagType = () => {
|
const EditTagType = () => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
@ -37,8 +38,8 @@ const EditTagType = () => {
|
|||||||
title: 'Tag type updated',
|
title: 'Tag type updated',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} catch (e: any) {
|
} catch (error: unknown) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import useTagTypesApi from '../../../hooks/api/actions/useTagTypesApi/useTagType
|
|||||||
import useTagTypes from '../../../hooks/api/getters/useTagTypes/useTagTypes';
|
import useTagTypes from '../../../hooks/api/getters/useTagTypes/useTagTypes';
|
||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
export const TagTypeList = () => {
|
export const TagTypeList = () => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
@ -46,8 +47,8 @@ export const TagTypeList = () => {
|
|||||||
show: true,
|
show: true,
|
||||||
text: 'Successfully deleted tag type.',
|
text: 'Successfully deleted tag type.',
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { useHistory } from 'react-router-dom';
|
|||||||
import { useAuthApi } from '../../../hooks/api/actions/useAuthApi/useAuthApi';
|
import { useAuthApi } from '../../../hooks/api/actions/useAuthApi/useAuthApi';
|
||||||
import { useAuthUser } from '../../../hooks/api/getters/useAuth/useAuthUser';
|
import { useAuthUser } from '../../../hooks/api/getters/useAuth/useAuthUser';
|
||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const DemoAuth = ({ authDetails }) => {
|
const DemoAuth = ({ authDetails }) => {
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
@ -23,8 +24,8 @@ const DemoAuth = ({ authDetails }) => {
|
|||||||
await emailAuth(authDetails.path, email);
|
await emailAuth(authDetails.path, email);
|
||||||
refetchUser();
|
refetchUser();
|
||||||
history.push(`/`);
|
history.push(`/`);
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { useAuthApi } from '../../../hooks/api/actions/useAuthApi/useAuthApi';
|
|||||||
import { useAuthUser } from '../../../hooks/api/getters/useAuth/useAuthUser';
|
import { useAuthUser } from '../../../hooks/api/getters/useAuth/useAuthUser';
|
||||||
import { LOGIN_BUTTON, LOGIN_EMAIL_ID } from '../../../testIds';
|
import { LOGIN_BUTTON, LOGIN_EMAIL_ID } from '../../../testIds';
|
||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
|
import { formatUnknownError } from '../../../utils/format-unknown-error';
|
||||||
|
|
||||||
const SimpleAuth = ({ authDetails }) => {
|
const SimpleAuth = ({ authDetails }) => {
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
@ -22,8 +23,8 @@ const SimpleAuth = ({ authDetails }) => {
|
|||||||
await emailAuth(authDetails.path, email);
|
await emailAuth(authDetails.path, email);
|
||||||
refetchUser();
|
refetchUser();
|
||||||
history.push(`/`);
|
history.push(`/`);
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
setToastApiError(e.toString());
|
setToastApiError(formatUnknownError(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { SyntheticEvent, useState } from 'react';
|
import React, { SyntheticEvent, useState } from 'react';
|
||||||
import { Button, Typography } from '@material-ui/core';
|
import { Button, Typography } from '@material-ui/core';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { useStyles } from './EditProfile.styles';
|
import { useStyles } from './EditProfile.styles';
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user