mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-19 01:17:18 +02:00
feat: multi-project api access tokens (#857)
* fix: general select component typings * custom multi-select for projects * autocomplete element for token projects * project multi-select with error handling * projects in tokens list update * multi-project tokens - select all button * fix conflicting typescript changes * improve multi-projects tokens form after review * refactor multi-project select code structure * test api token list projects column element * simplify test renderer
This commit is contained in:
parent
4b9271637d
commit
b23226370a
@ -42,7 +42,7 @@
|
||||
"@material-ui/lab": "4.0.0-alpha.61",
|
||||
"@testing-library/dom": "8.12.0",
|
||||
"@testing-library/jest-dom": "5.16.3",
|
||||
"@testing-library/react": "13.0.0",
|
||||
"@testing-library/react": "^12.1.4",
|
||||
"@testing-library/react-hooks": "^7.0.2",
|
||||
"@testing-library/user-event": "14.0.4",
|
||||
"@types/debounce": "1.2.1",
|
||||
|
@ -43,4 +43,10 @@ export const useStyles = makeStyles(theme => ({
|
||||
position: 'absolute',
|
||||
top: '-8px',
|
||||
},
|
||||
selectOptionsLink: {
|
||||
cursor: 'pointer',
|
||||
},
|
||||
selectOptionCheckbox: {
|
||||
marginRight: '0.2rem',
|
||||
},
|
||||
}));
|
||||
|
@ -6,54 +6,53 @@ import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
||||
import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
|
||||
import Input from 'component/common/Input/Input';
|
||||
import { useStyles } from './ApiTokenForm.styles';
|
||||
import { SelectProjectInput } from './SelectProjectInput/SelectProjectInput';
|
||||
import { ApiTokenFormErrorType } from '../hooks/useApiTokenForm';
|
||||
interface IApiTokenFormProps {
|
||||
username: string;
|
||||
type: string;
|
||||
project: string;
|
||||
projects: string[];
|
||||
environment?: string;
|
||||
setTokenType: (value: string) => void;
|
||||
setUsername: React.Dispatch<React.SetStateAction<string>>;
|
||||
setProject: React.Dispatch<React.SetStateAction<string>>;
|
||||
setProjects: React.Dispatch<React.SetStateAction<string[]>>;
|
||||
setEnvironment: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||
handleSubmit: (e: any) => void;
|
||||
handleCancel: () => void;
|
||||
errors: { [key: string]: string };
|
||||
mode: 'Create' | 'Edit';
|
||||
clearErrors: () => void;
|
||||
clearErrors: (error?: ApiTokenFormErrorType) => void;
|
||||
}
|
||||
|
||||
const ApiTokenForm: React.FC<IApiTokenFormProps> = ({
|
||||
children,
|
||||
username,
|
||||
type,
|
||||
project,
|
||||
projects,
|
||||
environment,
|
||||
setUsername,
|
||||
setTokenType,
|
||||
setProject,
|
||||
setProjects,
|
||||
setEnvironment,
|
||||
handleSubmit,
|
||||
handleCancel,
|
||||
errors,
|
||||
clearErrors,
|
||||
mode,
|
||||
}) => {
|
||||
const TYPE_ADMIN = 'ADMIN';
|
||||
const styles = useStyles();
|
||||
const { environments } = useEnvironments();
|
||||
const { projects } = useProjects();
|
||||
const { projects: availableProjects } = useProjects();
|
||||
|
||||
const selectableTypes = [
|
||||
{ key: 'CLIENT', label: 'Client', title: 'Client SDK token' },
|
||||
{ key: 'ADMIN', label: 'Admin', title: 'Admin API token' },
|
||||
];
|
||||
|
||||
const selectableProjects = [{ id: '*', name: 'ALL' }, ...projects].map(
|
||||
i => ({
|
||||
key: i.id,
|
||||
label: i.name,
|
||||
title: i.name,
|
||||
})
|
||||
);
|
||||
const selectableProjects = availableProjects.map(i => ({
|
||||
value: i.id,
|
||||
label: i.name,
|
||||
}));
|
||||
|
||||
const selectableEnvs =
|
||||
type === TYPE_ADMIN
|
||||
@ -79,7 +78,7 @@ const ApiTokenForm: React.FC<IApiTokenFormProps> = ({
|
||||
label="Username"
|
||||
error={errors.username !== undefined}
|
||||
errorText={errors.username}
|
||||
onFocus={() => clearErrors()}
|
||||
onFocus={() => clearErrors('username')}
|
||||
autoFocus
|
||||
/>
|
||||
<p className={styles.inputDescription}>
|
||||
@ -93,21 +92,19 @@ const ApiTokenForm: React.FC<IApiTokenFormProps> = ({
|
||||
id="api_key_type"
|
||||
name="type"
|
||||
IconComponent={KeyboardArrowDownOutlined}
|
||||
fullWidth
|
||||
className={styles.selectInput}
|
||||
/>
|
||||
<p className={styles.inputDescription}>
|
||||
Which project do you want to give access to?
|
||||
</p>
|
||||
<GeneralSelect
|
||||
<SelectProjectInput
|
||||
disabled={type === TYPE_ADMIN}
|
||||
value={project}
|
||||
options={selectableProjects}
|
||||
onChange={e => setProject(e.target.value as string)}
|
||||
label="Project"
|
||||
id="api_key_project"
|
||||
name="project"
|
||||
IconComponent={KeyboardArrowDownOutlined}
|
||||
className={styles.selectInput}
|
||||
defaultValue={projects}
|
||||
onChange={setProjects}
|
||||
error={errors?.projects}
|
||||
onFocus={() => clearErrors('projects')}
|
||||
/>
|
||||
<p className={styles.inputDescription}>
|
||||
Which environment should the token have access to?
|
||||
@ -121,6 +118,7 @@ const ApiTokenForm: React.FC<IApiTokenFormProps> = ({
|
||||
id="api_key_environment"
|
||||
name="environment"
|
||||
IconComponent={KeyboardArrowDownOutlined}
|
||||
fullWidth
|
||||
className={styles.selectInput}
|
||||
/>
|
||||
</div>
|
||||
|
@ -0,0 +1,7 @@
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
export const useStyles = makeStyles(theme => ({
|
||||
selectOptionsLink: {
|
||||
cursor: 'pointer',
|
||||
},
|
||||
}));
|
@ -0,0 +1,23 @@
|
||||
import React, { FC } from 'react';
|
||||
import { Box, Link } from '@material-ui/core';
|
||||
import { useStyles } from './SelectAllButton.styles';
|
||||
|
||||
type SelectAllButtonProps = {
|
||||
isAllSelected: boolean;
|
||||
onClick: () => void;
|
||||
};
|
||||
|
||||
export const SelectAllButton: FC<SelectAllButtonProps> = ({
|
||||
isAllSelected,
|
||||
onClick,
|
||||
}) => {
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<Box sx={{ ml: 3.5, my: 0.5 }}>
|
||||
<Link onClick={onClick} className={styles.selectOptionsLink}>
|
||||
{isAllSelected ? 'Deselect all' : 'Select all'}
|
||||
</Link>
|
||||
</Box>
|
||||
);
|
||||
};
|
@ -0,0 +1,7 @@
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
export const useStyles = makeStyles(theme => ({
|
||||
selectOptionCheckbox: {
|
||||
marginRight: '0.2rem',
|
||||
},
|
||||
}));
|
@ -0,0 +1,148 @@
|
||||
import React, { Fragment, useState, ChangeEvent, VFC } from 'react';
|
||||
import {
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
TextField,
|
||||
Box,
|
||||
Paper,
|
||||
} from '@material-ui/core';
|
||||
import {
|
||||
Autocomplete,
|
||||
AutocompleteRenderGroupParams,
|
||||
AutocompleteRenderInputParams,
|
||||
AutocompleteRenderOptionState,
|
||||
} from '@material-ui/lab';
|
||||
import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
|
||||
import CheckBoxIcon from '@material-ui/icons/CheckBox';
|
||||
import { IAutocompleteBoxOption } from 'component/common/AutocompleteBox/AutocompleteBox';
|
||||
import { useStyles } from '../ApiTokenForm.styles';
|
||||
import { SelectAllButton } from './SelectAllButton/SelectAllButton';
|
||||
|
||||
const ALL_PROJECTS = '*';
|
||||
|
||||
// Fix for shadow under Autocomplete - match with Select input
|
||||
const CustomPaper = ({ ...props }) => <Paper elevation={8} {...props} />;
|
||||
|
||||
interface ISelectProjectInputProps {
|
||||
disabled?: boolean;
|
||||
options: IAutocompleteBoxOption[];
|
||||
defaultValue: string[];
|
||||
onChange: (value: string[]) => void;
|
||||
onFocus?: () => void;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export const SelectProjectInput: VFC<ISelectProjectInputProps> = ({
|
||||
options,
|
||||
defaultValue = [ALL_PROJECTS],
|
||||
onChange,
|
||||
disabled,
|
||||
error,
|
||||
onFocus,
|
||||
}) => {
|
||||
const styles = useStyles();
|
||||
const [projects, setProjects] = useState<string[]>(
|
||||
typeof defaultValue === 'string' ? [defaultValue] : defaultValue
|
||||
);
|
||||
const [isWildcardSelected, selectWildcard] = useState(
|
||||
typeof defaultValue === 'string' || defaultValue.includes(ALL_PROJECTS)
|
||||
);
|
||||
const isAllSelected = projects.length === options.length;
|
||||
|
||||
const onAllProjectsChange = (
|
||||
e: ChangeEvent<HTMLInputElement>,
|
||||
checked: boolean
|
||||
) => {
|
||||
if (checked) {
|
||||
selectWildcard(true);
|
||||
onChange([ALL_PROJECTS]);
|
||||
} else {
|
||||
selectWildcard(false);
|
||||
onChange(projects.includes(ALL_PROJECTS) ? [] : projects);
|
||||
}
|
||||
};
|
||||
|
||||
const renderOption = (
|
||||
option: IAutocompleteBoxOption,
|
||||
{ selected }: AutocompleteRenderOptionState
|
||||
) => (
|
||||
<>
|
||||
<Checkbox
|
||||
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
|
||||
checkedIcon={<CheckBoxIcon fontSize="small" />}
|
||||
checked={selected}
|
||||
className={styles.selectOptionCheckbox}
|
||||
/>
|
||||
{option.label}
|
||||
</>
|
||||
);
|
||||
|
||||
const renderGroup = ({ key, children }: AutocompleteRenderGroupParams) => (
|
||||
<Fragment key={key}>
|
||||
<SelectAllButton
|
||||
isAllSelected={isAllSelected}
|
||||
onClick={() => {
|
||||
setProjects(
|
||||
isAllSelected ? [] : options.map(({ value }) => value)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{children}
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
const renderInput = (params: AutocompleteRenderInputParams) => (
|
||||
<TextField
|
||||
{...params}
|
||||
error={!!error}
|
||||
helperText={error}
|
||||
variant="outlined"
|
||||
label="Projects"
|
||||
placeholder="Select one or more projects"
|
||||
onFocus={onFocus}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Box sx={{ mt: -1, mb: 3 }}>
|
||||
<Box sx={{ mt: 1, mb: 0.25, ml: 1.5 }}>
|
||||
<FormControlLabel
|
||||
disabled={disabled}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={disabled || isWildcardSelected}
|
||||
onChange={onAllProjectsChange}
|
||||
/>
|
||||
}
|
||||
label="ALL current and future projects"
|
||||
/>
|
||||
</Box>
|
||||
<Autocomplete
|
||||
disabled={disabled || isWildcardSelected}
|
||||
multiple
|
||||
limitTags={2}
|
||||
options={options}
|
||||
disableCloseOnSelect
|
||||
getOptionLabel={({ label }) => label}
|
||||
groupBy={() => 'Select/Deselect all'}
|
||||
renderGroup={renderGroup}
|
||||
fullWidth
|
||||
PaperComponent={CustomPaper}
|
||||
renderOption={renderOption}
|
||||
renderInput={renderInput}
|
||||
value={
|
||||
isWildcardSelected || disabled
|
||||
? options
|
||||
: options.filter(option =>
|
||||
projects.includes(option.value)
|
||||
)
|
||||
}
|
||||
onChange={(_, input) => {
|
||||
const state = input.map(({ value }) => value);
|
||||
setProjects(state);
|
||||
onChange(state);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
import { useContext, useState } from 'react';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import { Fragment, useContext, useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
@ -32,13 +32,15 @@ import { Alert } from '@material-ui/lab';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
||||
import { formatDateYMD } from 'utils/formatDate';
|
||||
import { ProjectsList } from './ProjectsList/ProjectsList';
|
||||
|
||||
interface IApiToken {
|
||||
createdAt: Date;
|
||||
username: string;
|
||||
secret: string;
|
||||
type: string;
|
||||
project: string;
|
||||
project?: string;
|
||||
projects?: string | string[];
|
||||
environment: string;
|
||||
}
|
||||
|
||||
@ -89,14 +91,6 @@ export const ApiTokenList = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const renderProject = (projectId: string) => {
|
||||
if (!projectId || projectId === '*') {
|
||||
return projectId;
|
||||
} else {
|
||||
return <Link to={`/projects/${projectId}`}>{projectId}</Link>;
|
||||
}
|
||||
};
|
||||
|
||||
const renderApiTokens = (tokens: IApiToken[]) => {
|
||||
return (
|
||||
<Table size="small">
|
||||
@ -118,7 +112,7 @@ export const ApiTokenList = () => {
|
||||
<TableCell
|
||||
className={`${styles.center} ${styles.hideXS}`}
|
||||
>
|
||||
Project
|
||||
Projects
|
||||
</TableCell>
|
||||
<TableCell
|
||||
className={`${styles.center} ${styles.hideXS}`}
|
||||
@ -169,7 +163,10 @@ export const ApiTokenList = () => {
|
||||
<TableCell
|
||||
className={`${styles.center} ${styles.hideXS}`}
|
||||
>
|
||||
{renderProject(item.project)}
|
||||
<ProjectsList
|
||||
project={item.project}
|
||||
projects={item.projects}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
className={`${styles.center} ${styles.hideXS}`}
|
||||
@ -181,8 +178,11 @@ export const ApiTokenList = () => {
|
||||
<br />
|
||||
<b>Env:</b> {item.environment}
|
||||
<br />
|
||||
<b>Project:</b>{' '}
|
||||
{renderProject(item.project)}
|
||||
<b>Projects:</b>{' '}
|
||||
<ProjectsList
|
||||
project={item.project}
|
||||
projects={item.projects}
|
||||
/>
|
||||
</TableCell>
|
||||
</>
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { render } from 'utils/testRenderer';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { ProjectsList } from './ProjectsList';
|
||||
|
||||
describe('ProjectsList', () => {
|
||||
it('should prioritize new "projects" array over deprecated "project"', async () => {
|
||||
render(
|
||||
<ProjectsList
|
||||
project="project"
|
||||
projects={['project1', 'project2']}
|
||||
/>
|
||||
);
|
||||
|
||||
const links = await screen.findAllByRole('link');
|
||||
expect(links).toHaveLength(2);
|
||||
expect(links[0]).toHaveTextContent('project1');
|
||||
expect(links[1]).toHaveTextContent('project2');
|
||||
expect(links[0]).toHaveAttribute('href', '/projects/project1');
|
||||
expect(links[1]).toHaveAttribute('href', '/projects/project2');
|
||||
});
|
||||
|
||||
it('should render correctly with single "project"', async () => {
|
||||
render(<ProjectsList project="project" />);
|
||||
|
||||
const links = await screen.findAllByRole('link');
|
||||
expect(links).toHaveLength(1);
|
||||
expect(links[0]).toHaveTextContent('project');
|
||||
});
|
||||
|
||||
it('should have comma between project links', async () => {
|
||||
const { container } = render(<ProjectsList projects={['a', 'b']} />);
|
||||
|
||||
expect(container.textContent).toContain(', ');
|
||||
});
|
||||
|
||||
it('should render asterisk if no projects are passed', async () => {
|
||||
const { container } = render(<ProjectsList />);
|
||||
|
||||
expect(container.textContent).toEqual('*');
|
||||
});
|
||||
|
||||
it('should render asterisk if empty projects array is passed', async () => {
|
||||
const { container } = render(<ProjectsList projects={[]} />);
|
||||
|
||||
expect(container.textContent).toEqual('*');
|
||||
});
|
||||
});
|
@ -0,0 +1,33 @@
|
||||
import React, { Fragment, VFC } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
interface IProjectsListProps {
|
||||
project?: string;
|
||||
projects?: string | string[];
|
||||
}
|
||||
|
||||
export const ProjectsList: VFC<IProjectsListProps> = ({
|
||||
projects,
|
||||
project,
|
||||
}) => {
|
||||
let fields = projects && Array.isArray(projects) ? projects : [project];
|
||||
|
||||
if (fields.length === 0) {
|
||||
return <>*</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{fields.map((item, index) => (
|
||||
<Fragment key={item}>
|
||||
{index > 0 && ', '}
|
||||
{!item || item === '*' ? (
|
||||
'*'
|
||||
) : (
|
||||
<Link to={`/projects/${item}`}>{item}</Link>
|
||||
)}
|
||||
</Fragment>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
@ -23,11 +23,11 @@ export const CreateApiToken = () => {
|
||||
getApiTokenPayload,
|
||||
username,
|
||||
type,
|
||||
project,
|
||||
projects,
|
||||
environment,
|
||||
setUsername,
|
||||
setTokenType,
|
||||
setProject,
|
||||
setProjects,
|
||||
setEnvironment,
|
||||
isValid,
|
||||
errors,
|
||||
@ -84,12 +84,12 @@ export const CreateApiToken = () => {
|
||||
<ApiTokenForm
|
||||
username={username}
|
||||
type={type}
|
||||
project={project}
|
||||
projects={projects}
|
||||
environment={environment}
|
||||
setEnvironment={setEnvironment}
|
||||
setTokenType={setTokenType}
|
||||
setUsername={setUsername}
|
||||
setProject={setProject}
|
||||
setProjects={setProjects}
|
||||
errors={errors}
|
||||
handleSubmit={handleSubmit}
|
||||
handleCancel={handleCancel}
|
||||
|
@ -1,5 +1,8 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
|
||||
import { IApiTokenCreate } from 'hooks/api/actions/useApiTokensApi/useApiTokensApi';
|
||||
|
||||
export type ApiTokenFormErrorType = 'username' | 'projects';
|
||||
|
||||
export const useApiTokenForm = () => {
|
||||
const { environments } = useEnvironments();
|
||||
@ -7,9 +10,11 @@ export const useApiTokenForm = () => {
|
||||
|
||||
const [username, setUsername] = useState('');
|
||||
const [type, setType] = useState('CLIENT');
|
||||
const [project, setProject] = useState('*');
|
||||
const [projects, setProjects] = useState<string[]>(['*']);
|
||||
const [environment, setEnvironment] = useState<string>();
|
||||
const [errors, setErrors] = useState({});
|
||||
const [errors, setErrors] = useState<
|
||||
Partial<Record<ApiTokenFormErrorType, string>>
|
||||
>({});
|
||||
|
||||
useEffect(() => {
|
||||
setEnvironment(type === 'ADMIN' ? '*' : initialEnvironment);
|
||||
@ -18,7 +23,7 @@ export const useApiTokenForm = () => {
|
||||
const setTokenType = (value: string) => {
|
||||
if (value === 'ADMIN') {
|
||||
setType(value);
|
||||
setProject('*');
|
||||
setProjects(['*']);
|
||||
setEnvironment('*');
|
||||
} else {
|
||||
setType(value);
|
||||
@ -26,37 +31,44 @@ export const useApiTokenForm = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const getApiTokenPayload = () => {
|
||||
return {
|
||||
username: username,
|
||||
type: type,
|
||||
project: project,
|
||||
environment: environment,
|
||||
};
|
||||
};
|
||||
const getApiTokenPayload = (): IApiTokenCreate => ({
|
||||
username,
|
||||
type,
|
||||
environment,
|
||||
projects,
|
||||
});
|
||||
|
||||
const isValid = () => {
|
||||
const newErrors: Partial<Record<ApiTokenFormErrorType, string>> = {};
|
||||
if (!username) {
|
||||
setErrors({ username: 'Username is required.' });
|
||||
return false;
|
||||
} else {
|
||||
setErrors({});
|
||||
return true;
|
||||
newErrors['username'] = 'Username is required';
|
||||
}
|
||||
if (projects.length === 0) {
|
||||
newErrors['projects'] = 'At least one project is required';
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
|
||||
const clearErrors = () => {
|
||||
setErrors({});
|
||||
const clearErrors = (error?: ApiTokenFormErrorType) => {
|
||||
if (error) {
|
||||
const newErrors = { ...errors };
|
||||
delete newErrors[error];
|
||||
setErrors(newErrors);
|
||||
} else {
|
||||
setErrors({});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
username,
|
||||
type,
|
||||
project,
|
||||
projects,
|
||||
environment,
|
||||
setUsername,
|
||||
setTokenType,
|
||||
setProject,
|
||||
setProjects,
|
||||
setEnvironment,
|
||||
getApiTokenPayload,
|
||||
isValid,
|
||||
|
@ -17,17 +17,13 @@ export interface ISelectOption {
|
||||
}
|
||||
|
||||
export interface ISelectMenuProps extends SelectProps {
|
||||
name: string;
|
||||
id: string;
|
||||
name?: string;
|
||||
value?: string;
|
||||
label?: string;
|
||||
autoFocus?: boolean;
|
||||
options: ISelectOption[];
|
||||
style?: object;
|
||||
onChange?: OnGeneralSelectChange;
|
||||
disabled?: boolean;
|
||||
fullWidth?: boolean;
|
||||
className?: string;
|
||||
classes?: any;
|
||||
defaultValue?: string;
|
||||
}
|
||||
@ -43,10 +39,8 @@ const GeneralSelect: React.FC<ISelectMenuProps> = ({
|
||||
label = '',
|
||||
options,
|
||||
onChange,
|
||||
defaultValue,
|
||||
id,
|
||||
disabled = false,
|
||||
autoFocus,
|
||||
className,
|
||||
classes,
|
||||
fullWidth,
|
||||
@ -74,13 +68,11 @@ const GeneralSelect: React.FC<ISelectMenuProps> = ({
|
||||
>
|
||||
<InputLabel htmlFor={id}>{label}</InputLabel>
|
||||
<Select
|
||||
defaultValue={defaultValue}
|
||||
name={name}
|
||||
disabled={disabled}
|
||||
onChange={onChange}
|
||||
className={className}
|
||||
label={label}
|
||||
autoFocus={autoFocus}
|
||||
id={id}
|
||||
value={value}
|
||||
IconComponent={KeyboardArrowDownOutlined}
|
||||
|
@ -30,7 +30,6 @@ const FeatureTypeSelect = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* @ts-expect-error */}
|
||||
<GeneralSelect
|
||||
disabled={!editable}
|
||||
options={options}
|
||||
|
@ -115,7 +115,6 @@ const FeatureOverviewVariants = () => {
|
||||
|
||||
return (
|
||||
<section style={{ paddingTop: '16px' }}>
|
||||
{/* @ts-expect-error */}
|
||||
<GeneralSelect
|
||||
label="Stickiness"
|
||||
options={options}
|
||||
|
@ -3,8 +3,8 @@ import useAPI from '../useApi/useApi';
|
||||
export interface IApiTokenCreate {
|
||||
username: string;
|
||||
type: string;
|
||||
project: string;
|
||||
environment?: string;
|
||||
projects: string[];
|
||||
}
|
||||
|
||||
const useApiTokensApi = () => {
|
||||
|
17
frontend/src/utils/testRenderer.tsx
Normal file
17
frontend/src/utils/testRenderer.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { render as rtlRender, RenderOptions } from '@testing-library/react';
|
||||
|
||||
export const render = (
|
||||
ui: JSX.Element,
|
||||
{
|
||||
route = '/',
|
||||
...renderOptions
|
||||
}: { route?: string } & Omit<RenderOptions, 'queries'> = {}
|
||||
) => {
|
||||
window.history.pushState({}, 'Test page', route);
|
||||
|
||||
return rtlRender(ui, {
|
||||
wrapper: Router,
|
||||
...renderOptions,
|
||||
});
|
||||
};
|
@ -31,24 +31,24 @@
|
||||
integrity sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==
|
||||
|
||||
"@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
|
||||
version "7.17.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.8.tgz#3dac27c190ebc3a4381110d46c80e77efe172e1a"
|
||||
integrity sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.9.tgz#6bae81a06d95f4d0dec5bb9d74bbc1f58babdcfe"
|
||||
integrity sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==
|
||||
dependencies:
|
||||
"@ampproject/remapping" "^2.1.0"
|
||||
"@babel/code-frame" "^7.16.7"
|
||||
"@babel/generator" "^7.17.7"
|
||||
"@babel/generator" "^7.17.9"
|
||||
"@babel/helper-compilation-targets" "^7.17.7"
|
||||
"@babel/helper-module-transforms" "^7.17.7"
|
||||
"@babel/helpers" "^7.17.8"
|
||||
"@babel/parser" "^7.17.8"
|
||||
"@babel/helpers" "^7.17.9"
|
||||
"@babel/parser" "^7.17.9"
|
||||
"@babel/template" "^7.16.7"
|
||||
"@babel/traverse" "^7.17.3"
|
||||
"@babel/traverse" "^7.17.9"
|
||||
"@babel/types" "^7.17.0"
|
||||
convert-source-map "^1.7.0"
|
||||
debug "^4.1.0"
|
||||
gensync "^1.0.0-beta.2"
|
||||
json5 "^2.1.2"
|
||||
json5 "^2.2.1"
|
||||
semver "^6.3.0"
|
||||
|
||||
"@babel/eslint-parser@^7.16.3":
|
||||
@ -60,10 +60,10 @@
|
||||
eslint-visitor-keys "^2.1.0"
|
||||
semver "^6.3.0"
|
||||
|
||||
"@babel/generator@^7.17.3", "@babel/generator@^7.17.7", "@babel/generator@^7.7.2":
|
||||
version "7.17.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.7.tgz#8da2599beb4a86194a3b24df6c085931d9ee45ad"
|
||||
integrity sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==
|
||||
"@babel/generator@^7.17.9", "@babel/generator@^7.7.2":
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.9.tgz#f4af9fd38fa8de143c29fce3f71852406fc1e2fc"
|
||||
integrity sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==
|
||||
dependencies:
|
||||
"@babel/types" "^7.17.0"
|
||||
jsesc "^2.5.1"
|
||||
@ -94,15 +94,15 @@
|
||||
browserslist "^4.17.5"
|
||||
semver "^6.3.0"
|
||||
|
||||
"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.6":
|
||||
version "7.17.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz#3778c1ed09a7f3e65e6d6e0f6fbfcc53809d92c9"
|
||||
integrity sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==
|
||||
"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.6", "@babel/helper-create-class-features-plugin@^7.17.9":
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz#71835d7fb9f38bd9f1378e40a4c0902fdc2ea49d"
|
||||
integrity sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.16.7"
|
||||
"@babel/helper-environment-visitor" "^7.16.7"
|
||||
"@babel/helper-function-name" "^7.16.7"
|
||||
"@babel/helper-member-expression-to-functions" "^7.16.7"
|
||||
"@babel/helper-function-name" "^7.17.9"
|
||||
"@babel/helper-member-expression-to-functions" "^7.17.7"
|
||||
"@babel/helper-optimise-call-expression" "^7.16.7"
|
||||
"@babel/helper-replace-supers" "^7.16.7"
|
||||
"@babel/helper-split-export-declaration" "^7.16.7"
|
||||
@ -143,21 +143,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.16.7"
|
||||
|
||||
"@babel/helper-function-name@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f"
|
||||
integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==
|
||||
"@babel/helper-function-name@^7.16.7", "@babel/helper-function-name@^7.17.9":
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12"
|
||||
integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==
|
||||
dependencies:
|
||||
"@babel/helper-get-function-arity" "^7.16.7"
|
||||
"@babel/template" "^7.16.7"
|
||||
"@babel/types" "^7.16.7"
|
||||
|
||||
"@babel/helper-get-function-arity@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419"
|
||||
integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.16.7"
|
||||
"@babel/types" "^7.17.0"
|
||||
|
||||
"@babel/helper-hoist-variables@^7.16.7":
|
||||
version "7.16.7"
|
||||
@ -166,7 +158,7 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.16.7"
|
||||
|
||||
"@babel/helper-member-expression-to-functions@^7.16.7":
|
||||
"@babel/helper-member-expression-to-functions@^7.16.7", "@babel/helper-member-expression-to-functions@^7.17.7":
|
||||
version "7.17.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz#a34013b57d8542a8c4ff8ba3f747c02452a4d8c4"
|
||||
integrity sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==
|
||||
@ -267,28 +259,28 @@
|
||||
"@babel/traverse" "^7.16.8"
|
||||
"@babel/types" "^7.16.8"
|
||||
|
||||
"@babel/helpers@^7.17.8":
|
||||
version "7.17.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.8.tgz#288450be8c6ac7e4e44df37bcc53d345e07bc106"
|
||||
integrity sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==
|
||||
"@babel/helpers@^7.17.9":
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.9.tgz#b2af120821bfbe44f9907b1826e168e819375a1a"
|
||||
integrity sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==
|
||||
dependencies:
|
||||
"@babel/template" "^7.16.7"
|
||||
"@babel/traverse" "^7.17.3"
|
||||
"@babel/traverse" "^7.17.9"
|
||||
"@babel/types" "^7.17.0"
|
||||
|
||||
"@babel/highlight@^7.16.7":
|
||||
version "7.16.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88"
|
||||
integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.9.tgz#61b2ee7f32ea0454612def4fccdae0de232b73e3"
|
||||
integrity sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.16.7"
|
||||
chalk "^2.0.0"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.17.8":
|
||||
version "7.17.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.8.tgz#2817fb9d885dd8132ea0f8eb615a6388cca1c240"
|
||||
integrity sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.9":
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.9.tgz#9c94189a6062f0291418ca021077983058e171ef"
|
||||
integrity sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==
|
||||
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7":
|
||||
version "7.16.7"
|
||||
@ -333,13 +325,14 @@
|
||||
"@babel/plugin-syntax-class-static-block" "^7.14.5"
|
||||
|
||||
"@babel/plugin-proposal-decorators@^7.16.4":
|
||||
version "7.17.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.8.tgz#4f0444e896bee85d35cf714a006fc5418f87ff00"
|
||||
integrity sha512-U69odN4Umyyx1xO1rTII0IDkAEC+RNlcKXtqOblfpzqy1C+aOplb76BQNq0+XdpVkOaPlpEDwd++joY8FNFJKA==
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.9.tgz#67a1653be9c77ce5b6c318aa90c8287b87831619"
|
||||
integrity sha512-EfH2LZ/vPa2wuPwJ26j+kYRkaubf89UlwxKXtxqEm57HrgSEYDB8t4swFP+p8LcI9yiP9ZRJJjo/58hS6BnaDA==
|
||||
dependencies:
|
||||
"@babel/helper-create-class-features-plugin" "^7.17.6"
|
||||
"@babel/helper-create-class-features-plugin" "^7.17.9"
|
||||
"@babel/helper-plugin-utils" "^7.16.7"
|
||||
"@babel/helper-replace-supers" "^7.16.7"
|
||||
"@babel/helper-split-export-declaration" "^7.16.7"
|
||||
"@babel/plugin-syntax-decorators" "^7.17.0"
|
||||
charcodes "^0.2.0"
|
||||
|
||||
@ -714,9 +707,9 @@
|
||||
babel-plugin-dynamic-import-node "^2.3.3"
|
||||
|
||||
"@babel/plugin-transform-modules-commonjs@^7.16.8":
|
||||
version "7.17.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.7.tgz#d86b217c8e45bb5f2dbc11eefc8eab62cf980d19"
|
||||
integrity sha512-ITPmR2V7MqioMJyrxUo2onHNC3e+MvfFiFIR0RP21d3PtlVb6sfzoxNKiphSZUOM9hEIdzCcZe83ieX3yoqjUA==
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.9.tgz#274be1a2087beec0254d4abd4d86e52442e1e5b6"
|
||||
integrity sha512-2TBFd/r2I6VlYn0YRTz2JdazS+FoUuQ2rIFHoAxtyP/0G3D82SBLaRq9rnUkpqlLg03Byfl/+M32mpxjO6KaPw==
|
||||
dependencies:
|
||||
"@babel/helper-module-transforms" "^7.17.7"
|
||||
"@babel/helper-plugin-utils" "^7.16.7"
|
||||
@ -819,11 +812,11 @@
|
||||
"@babel/helper-plugin-utils" "^7.16.7"
|
||||
|
||||
"@babel/plugin-transform-regenerator@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb"
|
||||
integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.17.9.tgz#0a33c3a61cf47f45ed3232903683a0afd2d3460c"
|
||||
integrity sha512-Lc2TfbxR1HOyn/c6b4Y/b6NHoTb67n/IoWLxTu4kC7h4KQnWlhCq2S8Tx0t2SVvv5Uu87Hs+6JEJ5kt2tYGylQ==
|
||||
dependencies:
|
||||
regenerator-transform "^0.14.2"
|
||||
regenerator-transform "^0.15.0"
|
||||
|
||||
"@babel/plugin-transform-reserved-words@^7.16.7":
|
||||
version "7.16.7"
|
||||
@ -1017,17 +1010,17 @@
|
||||
"@babel/plugin-transform-typescript" "^7.16.7"
|
||||
|
||||
"@babel/runtime-corejs3@^7.10.2":
|
||||
version "7.17.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.8.tgz#d7dd49fb812f29c61c59126da3792d8740d4e284"
|
||||
integrity sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ==
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.9.tgz#3d02d0161f0fbf3ada8e88159375af97690f4055"
|
||||
integrity sha512-WxYHHUWF2uZ7Hp1K+D1xQgbgkGUfA+5UPOegEXGt2Y5SMog/rYCVaifLZDbw8UkNXozEqqrZTy6bglL7xTaCOw==
|
||||
dependencies:
|
||||
core-js-pure "^3.20.2"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
|
||||
version "7.17.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2"
|
||||
integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72"
|
||||
integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
@ -1040,18 +1033,18 @@
|
||||
"@babel/parser" "^7.16.7"
|
||||
"@babel/types" "^7.16.7"
|
||||
|
||||
"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.3", "@babel/traverse@^7.7.2":
|
||||
version "7.17.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57"
|
||||
integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==
|
||||
"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.3", "@babel/traverse@^7.17.9", "@babel/traverse@^7.7.2":
|
||||
version "7.17.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.9.tgz#1f9b207435d9ae4a8ed6998b2b82300d83c37a0d"
|
||||
integrity sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.16.7"
|
||||
"@babel/generator" "^7.17.3"
|
||||
"@babel/generator" "^7.17.9"
|
||||
"@babel/helper-environment-visitor" "^7.16.7"
|
||||
"@babel/helper-function-name" "^7.16.7"
|
||||
"@babel/helper-function-name" "^7.17.9"
|
||||
"@babel/helper-hoist-variables" "^7.16.7"
|
||||
"@babel/helper-split-export-declaration" "^7.16.7"
|
||||
"@babel/parser" "^7.17.3"
|
||||
"@babel/parser" "^7.17.9"
|
||||
"@babel/types" "^7.17.0"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
@ -1709,7 +1702,7 @@
|
||||
"@svgr/plugin-svgo" "^5.5.0"
|
||||
loader-utils "^2.0.0"
|
||||
|
||||
"@testing-library/dom@8.12.0", "@testing-library/dom@^8.5.0":
|
||||
"@testing-library/dom@8.12.0":
|
||||
version "8.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.12.0.tgz#fef5e545533fb084175dda6509ee71d7d2f72e23"
|
||||
integrity sha512-rBrJk5WjI02X1edtiUcZhgyhgBhiut96r5Jp8J5qktKdcvLcZpKDW8i2hkGMMItxrghjXuQ5AM6aE0imnFawaw==
|
||||
@ -1723,6 +1716,20 @@
|
||||
lz-string "^1.4.4"
|
||||
pretty-format "^27.0.2"
|
||||
|
||||
"@testing-library/dom@^8.0.0":
|
||||
version "8.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.13.0.tgz#bc00bdd64c7d8b40841e27a70211399ad3af46f5"
|
||||
integrity sha512-9VHgfIatKNXQNaZTtLnalIy0jNZzY35a4S3oi08YAt9Hv1VsfZ/DfA45lM8D/UhtHBGJ4/lGwp0PZkVndRkoOQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.10.4"
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@types/aria-query" "^4.2.0"
|
||||
aria-query "^5.0.0"
|
||||
chalk "^4.1.0"
|
||||
dom-accessibility-api "^0.5.9"
|
||||
lz-string "^1.4.4"
|
||||
pretty-format "^27.0.2"
|
||||
|
||||
"@testing-library/jest-dom@5.16.3":
|
||||
version "5.16.3"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.3.tgz#b76851a909586113c20486f1679ffb4d8ec27bfa"
|
||||
@ -1749,13 +1756,13 @@
|
||||
"@types/react-test-renderer" ">=16.9.0"
|
||||
react-error-boundary "^3.1.0"
|
||||
|
||||
"@testing-library/react@13.0.0":
|
||||
version "13.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.0.0.tgz#8cdaf4667c6c2b082eb0513731551e9db784e8bc"
|
||||
integrity sha512-p0lYA1M7uoEmk2LnCbZLGmHJHyH59sAaZVXChTXlyhV/PRW9LoIh4mdf7tiXsO8BoNG+vN8UnFJff1hbZeXv+w==
|
||||
"@testing-library/react@^12.1.4":
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.4.tgz#09674b117e550af713db3f4ec4c0942aa8bbf2c0"
|
||||
integrity sha512-jiPKOm7vyUw311Hn/HlNQ9P8/lHNtArAx0PisXyFixDDvfl8DbD6EUdbshK5eqauvBSvzZd19itqQ9j3nferJA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@testing-library/dom" "^8.5.0"
|
||||
"@testing-library/dom" "^8.0.0"
|
||||
"@types/react-dom" "*"
|
||||
|
||||
"@testing-library/user-event@14.0.4":
|
||||
@ -4098,9 +4105,9 @@ ejs@^3.1.6:
|
||||
jake "^10.6.1"
|
||||
|
||||
electron-to-chromium@^1.4.84:
|
||||
version "1.4.103"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.103.tgz#abfe376a4d70fa1e1b4b353b95df5d6dfd05da3a"
|
||||
integrity sha512-c/uKWR1Z/W30Wy/sx3dkZoj4BijbXX85QKWu9jJfjho3LBAXNEGAEW3oWiGb+dotA6C6BzCTxL2/aLes7jlUeg==
|
||||
version "1.4.105"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.105.tgz#30de5e4ba020140b698539b2d366cd9c3a337ec7"
|
||||
integrity sha512-6w2bmoQBSUgCQjbSjiVv9IS1lXwW2aQABlUJ1vlE8Vci/sVXxUNQrHLQa5N1ioc82Py+a36DlUA5KvrAlHMMeA==
|
||||
|
||||
emittery@^0.8.1:
|
||||
version "0.8.1"
|
||||
@ -4273,7 +4280,7 @@ eslint-import-resolver-node@^0.3.6:
|
||||
debug "^3.2.7"
|
||||
resolve "^1.20.0"
|
||||
|
||||
eslint-module-utils@^2.7.2:
|
||||
eslint-module-utils@^2.7.3:
|
||||
version "2.7.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee"
|
||||
integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==
|
||||
@ -4290,23 +4297,23 @@ eslint-plugin-flowtype@^8.0.3:
|
||||
string-natural-compare "^3.0.1"
|
||||
|
||||
eslint-plugin-import@^2.25.3:
|
||||
version "2.25.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1"
|
||||
integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==
|
||||
version "2.26.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b"
|
||||
integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==
|
||||
dependencies:
|
||||
array-includes "^3.1.4"
|
||||
array.prototype.flat "^1.2.5"
|
||||
debug "^2.6.9"
|
||||
doctrine "^2.1.0"
|
||||
eslint-import-resolver-node "^0.3.6"
|
||||
eslint-module-utils "^2.7.2"
|
||||
eslint-module-utils "^2.7.3"
|
||||
has "^1.0.3"
|
||||
is-core-module "^2.8.0"
|
||||
is-core-module "^2.8.1"
|
||||
is-glob "^4.0.3"
|
||||
minimatch "^3.0.4"
|
||||
minimatch "^3.1.2"
|
||||
object.values "^1.1.5"
|
||||
resolve "^1.20.0"
|
||||
tsconfig-paths "^3.12.0"
|
||||
resolve "^1.22.0"
|
||||
tsconfig-paths "^3.14.1"
|
||||
|
||||
eslint-plugin-jest@^25.3.0:
|
||||
version "25.7.0"
|
||||
@ -4808,9 +4815,9 @@ forever-agent@~0.6.1:
|
||||
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
|
||||
|
||||
fork-ts-checker-webpack-plugin@^6.5.0:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e"
|
||||
integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.1.tgz#fd689e2d9de6ac76abb620909eea56438cd0f232"
|
||||
integrity sha512-x1wumpHOEf4gDROmKTaB6i4/Q6H3LwmjVO7fIX47vBwlZbtPjU33hgoMuD/Q/y6SU8bnuYSoN6ZQOLshGp0T/g==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.8.3"
|
||||
"@types/json-schema" "^7.0.5"
|
||||
@ -5445,7 +5452,7 @@ is-ci@^3.0.0:
|
||||
dependencies:
|
||||
ci-info "^3.2.0"
|
||||
|
||||
is-core-module@^2.2.0, is-core-module@^2.8.0, is-core-module@^2.8.1:
|
||||
is-core-module@^2.2.0, is-core-module@^2.8.1:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
|
||||
integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
|
||||
@ -6218,7 +6225,7 @@ json5@^1.0.1:
|
||||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
|
||||
json5@^2.1.2, json5@^2.2.0:
|
||||
json5@^2.1.2, json5@^2.2.0, json5@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
|
||||
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
|
||||
@ -6523,12 +6530,10 @@ lower-case@^2.0.2:
|
||||
dependencies:
|
||||
tslib "^2.0.3"
|
||||
|
||||
lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
lru-cache@^7.4.0:
|
||||
version "7.7.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.7.3.tgz#98cd19eef89ce6a4a3c4502c17c833888677c252"
|
||||
integrity sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw==
|
||||
|
||||
lru-cache@^7.4.0:
|
||||
version "7.7.3"
|
||||
@ -7232,9 +7237,9 @@ postcss-custom-media@^8.0.0:
|
||||
integrity sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==
|
||||
|
||||
postcss-custom-properties@^12.1.5:
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.5.tgz#e669cfff89b0ea6fc85c45864a32b450cb6b196f"
|
||||
integrity sha512-FHbbB/hRo/7cxLGkc2NS7cDRIDN1oFqQnUKBiyh4b/gwk8DD8udvmRDpUhEK836kB8ggUCieHVOvZDnF9XhI3g==
|
||||
version "12.1.6"
|
||||
resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.6.tgz#345b5b64c9520bb66390393646e8d5fbb7f10b58"
|
||||
integrity sha512-QEnQkDkb+J+j2bfJisJJpTAFL+lUFl66rUNvnjPBIvRbZACLG4Eu5bmBCIY4FJCqhwsfbBpmJUyb3FcR/31lAg==
|
||||
dependencies:
|
||||
postcss-value-parser "^4.2.0"
|
||||
|
||||
@ -7934,16 +7939,21 @@ react-hooks-global-state@1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/react-hooks-global-state/-/react-hooks-global-state-1.0.2.tgz#37bbc3203a0be9f3ac0658abfd28dd7ce7ee166c"
|
||||
integrity sha512-UcWz+VjcUUCQ7bXGmOhanGII3j22zyPSjwJnQWeycxFYj/etBxIbz9xziEm4sv5+OqGuS7bzvpx24XkCxgJ7Bg==
|
||||
|
||||
"react-is@^16.12.0 || ^17.0.0", "react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1, react-is@^17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
||||
"react-is@^16.12.0 || ^17.0.0 || ^18.0.0":
|
||||
version "18.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.0.0.tgz#026f6c4a27dbe33bf4a35655b9e1327c4e55e3f5"
|
||||
integrity sha512-yUcBYdBBbo3QiPsgYDcfQcIkGZHfxOaoE6HLSnr1sPzMhdyxusbfKOSUbSd/ocGi32dxcj366PsTj+5oggeKKw==
|
||||
|
||||
react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
"react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1, react-is@^17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
||||
|
||||
react-refresh@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
|
||||
@ -8034,12 +8044,12 @@ react-scripts@5.0.0:
|
||||
fsevents "^2.3.2"
|
||||
|
||||
react-shallow-renderer@^16.13.1:
|
||||
version "16.14.1"
|
||||
resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz#bf0d02df8a519a558fd9b8215442efa5c840e124"
|
||||
integrity sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg==
|
||||
version "16.15.0"
|
||||
resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457"
|
||||
integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==
|
||||
dependencies:
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.12.0 || ^17.0.0"
|
||||
react-is "^16.12.0 || ^17.0.0 || ^18.0.0"
|
||||
|
||||
react-test-renderer@17.0.2:
|
||||
version "17.0.2"
|
||||
@ -8142,10 +8152,10 @@ regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.9:
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
|
||||
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
|
||||
|
||||
regenerator-transform@^0.14.2:
|
||||
version "0.14.5"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4"
|
||||
integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==
|
||||
regenerator-transform@^0.15.0:
|
||||
version "0.15.0"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537"
|
||||
integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.8.4"
|
||||
|
||||
@ -8469,11 +8479,11 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
semver@^7.3.2, semver@^7.3.5:
|
||||
version "7.3.5"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
|
||||
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
|
||||
version "7.3.6"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.6.tgz#5d73886fb9c0c6602e79440b97165c29581cbb2b"
|
||||
integrity sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
lru-cache "^7.4.0"
|
||||
|
||||
send@0.17.2:
|
||||
version "0.17.2"
|
||||
@ -9159,7 +9169,7 @@ tryer@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
|
||||
integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
|
||||
|
||||
tsconfig-paths@^3.12.0:
|
||||
tsconfig-paths@^3.14.1:
|
||||
version "3.14.1"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a"
|
||||
integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==
|
||||
@ -9455,9 +9465,9 @@ webpack-dev-middleware@^5.3.1:
|
||||
schema-utils "^4.0.0"
|
||||
|
||||
webpack-dev-server@^4.6.0:
|
||||
version "4.8.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.8.0.tgz#022bb845946e31ca01527509a942869ecfc7e047"
|
||||
integrity sha512-yZ7OWVP1nOtv8s10R/ZCsH6zf6QKkNusMRBE9DsQbOknRzKaFYYrbwVPCXp8ynUOTt3RlD9szM8H0pUlrJ6wcw==
|
||||
version "4.8.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.8.1.tgz#58f9d797710d6e25fa17d6afab8708f958c11a29"
|
||||
integrity sha512-dwld70gkgNJa33czmcj/PlKY/nOy/BimbrgZRaR9vDATBQAYgLzggR0nxDtPLJiLrMgZwbE6RRfJ5vnBBasTyg==
|
||||
dependencies:
|
||||
"@types/bonjour" "^3.5.9"
|
||||
"@types/connect-history-api-fallback" "^1.3.5"
|
||||
@ -9859,11 +9869,6 @@ y18n@^5.0.5:
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
|
||||
|
||||
yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
|
Loading…
Reference in New Issue
Block a user