mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
Merge branch 'master' into feat/view-password
This commit is contained in:
commit
b3eed697b2
@ -48,7 +48,7 @@
|
||||
"@types/enzyme": "3.10.10",
|
||||
"@types/enzyme-adapter-react-16": "1.0.6",
|
||||
"@types/jest": "27.0.3",
|
||||
"@types/node": "14.18.1",
|
||||
"@types/node": "14.18.2",
|
||||
"@types/react": "17.0.37",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"@types/react-router-dom": "5.3.2",
|
||||
@ -87,7 +87,7 @@
|
||||
"redux-devtools-extension": "2.13.9",
|
||||
"redux-mock-store": "1.5.4",
|
||||
"redux-thunk": "2.4.1",
|
||||
"sass": "1.44.0",
|
||||
"sass": "1.45.1",
|
||||
"swr": "1.0.1",
|
||||
"typescript": "4.5.4",
|
||||
"web-vitals": "2.1.2"
|
||||
|
@ -7,6 +7,7 @@ export const useStyles = makeStyles(theme => ({
|
||||
position: 'relative',
|
||||
width: '50px',
|
||||
height: '100%',
|
||||
padding: '15px 0px',
|
||||
},
|
||||
vertical: {
|
||||
borderRadius: '1px',
|
||||
|
@ -3,7 +3,6 @@ import { makeStyles } from '@material-ui/core/styles';
|
||||
export const useStyles = makeStyles(theme => ({
|
||||
splashMainContainer: {
|
||||
backgroundColor: theme.palette.primary.light,
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
|
@ -19,6 +19,13 @@ export const useStyles = makeStyles(theme => ({
|
||||
position: 'relative',
|
||||
paddingBottom: '1rem',
|
||||
},
|
||||
header: {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
|
||||
paddingTop: '1.5rem',
|
||||
},
|
||||
headerTitle: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
@ -70,8 +77,8 @@ export const useStyles = makeStyles(theme => ({
|
||||
alignItems: 'center',
|
||||
},
|
||||
percentageContainer: {
|
||||
width: '50px',
|
||||
height: '50px',
|
||||
width: '90px',
|
||||
height: '90px',
|
||||
border: `2px solid ${theme.palette.primary.light}`,
|
||||
borderRadius: '50%',
|
||||
display: 'flex',
|
||||
@ -95,6 +102,7 @@ export const useStyles = makeStyles(theme => ({
|
||||
requestText: {
|
||||
textAlign: 'center',
|
||||
marginTop: '1rem',
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
},
|
||||
linkContainer: {
|
||||
display: 'flex',
|
||||
@ -114,6 +122,29 @@ export const useStyles = makeStyles(theme => ({
|
||||
fill: theme.palette.grey[400],
|
||||
marginBottom: '1rem',
|
||||
},
|
||||
strategiesText: {
|
||||
fontSize: '14px',
|
||||
color: theme.palette.grey[700],
|
||||
},
|
||||
stratigiesInfoContainer: {
|
||||
display: 'flex',
|
||||
},
|
||||
noStratigiesInfoContainer: {
|
||||
top: '1px',
|
||||
position: 'relative',
|
||||
},
|
||||
stratigiesIconsContainer: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
transform: 'scale(0.8)',
|
||||
top: '3px',
|
||||
left: '-10px',
|
||||
position: 'relative',
|
||||
[theme.breakpoints.down(560)]: {
|
||||
marginLeft: '0px',
|
||||
top: '5px',
|
||||
},
|
||||
},
|
||||
[theme.breakpoints.down(750)]: {
|
||||
accordionBodyFooter: {
|
||||
flexDirection: 'column',
|
||||
@ -124,7 +155,7 @@ export const useStyles = makeStyles(theme => ({
|
||||
},
|
||||
[theme.breakpoints.down(560)]: {
|
||||
disabledIndicatorPos: {
|
||||
top: '-8px',
|
||||
top: '13px',
|
||||
},
|
||||
headerTitle: {
|
||||
flexDirection: 'column',
|
||||
@ -135,6 +166,9 @@ export const useStyles = makeStyles(theme => ({
|
||||
truncator: {
|
||||
textAlign: 'center',
|
||||
},
|
||||
resultContainer: {
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
},
|
||||
[theme.breakpoints.down(400)]: {
|
||||
accordionHeader: {
|
||||
@ -145,4 +179,60 @@ export const useStyles = makeStyles(theme => ({
|
||||
padding: '0.5rem',
|
||||
},
|
||||
},
|
||||
strategyIconContainer: {
|
||||
marginRight: '5px',
|
||||
},
|
||||
strategyIcon: {
|
||||
fill: theme.palette.grey[600],
|
||||
},
|
||||
container: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginLeft: '1.3rem',
|
||||
[theme.breakpoints.down(560)]: {
|
||||
flexDirection: 'column',
|
||||
marginLeft: '0',
|
||||
},
|
||||
},
|
||||
addStrategyButton: {
|
||||
background: 'none',
|
||||
textDecoration: 'none',
|
||||
boxShadow: 'none',
|
||||
color: theme.palette.primary.main,
|
||||
fontWeight: 'normal',
|
||||
'&:hover': {
|
||||
background: 'none',
|
||||
textDecoration: 'none',
|
||||
boxShadow: 'none',
|
||||
color: theme.palette.primary.main,
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
'&:disabled': {
|
||||
margin: '0px 16px',
|
||||
height: '35px'
|
||||
},
|
||||
},
|
||||
separtor: {
|
||||
marginLeft: '-10px',
|
||||
marginRight: '9px',
|
||||
[theme.breakpoints.down(560)]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
resultContainer: {
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
justifyContent: 'space-around',
|
||||
},
|
||||
dataContainer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: '0px 15px',
|
||||
},
|
||||
resultTitle: {
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
}));
|
||||
|
@ -2,24 +2,38 @@ import {
|
||||
Accordion,
|
||||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
Tooltip,
|
||||
} from '@material-ui/core';
|
||||
import { ExpandMore } from '@material-ui/icons';
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature';
|
||||
import useFeatureMetrics from '../../../../../../hooks/api/getters/useFeatureMetrics/useFeatureMetrics';
|
||||
import { IFeatureEnvironment } from '../../../../../../interfaces/featureToggle';
|
||||
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
||||
import { getFeatureMetrics } from '../../../../../../utils/get-feature-metrics';
|
||||
import {
|
||||
getFeatureStrategyIcon,
|
||||
getHumanReadableStrategyName,
|
||||
} from '../../../../../../utils/strategy-names';
|
||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||
import DisabledIndicator from '../../../../../common/DisabledIndicator/DisabledIndicator';
|
||||
import EnvironmentIcon from '../../../../../common/EnvironmentIcon/EnvironmentIcon';
|
||||
import PermissionButton from '../../../../../common/PermissionButton/PermissionButton';
|
||||
import StringTruncator from '../../../../../common/StringTruncator/StringTruncator';
|
||||
import { UPDATE_FEATURE } from '../../../../../providers/AccessProvider/permissions';
|
||||
|
||||
import { useStyles } from './FeatureOverviewEnvironment.styles';
|
||||
import FeatureOverviewEnvironmentBody from './FeatureOverviewEnvironmentBody/FeatureOverviewEnvironmentBody';
|
||||
import FeatureOverviewEnvironmentFooter from './FeatureOverviewEnvironmentFooter/FeatureOverviewEnvironmentFooter';
|
||||
import FeatureOverviewEnvironmentMetrics from './FeatureOverviewEnvironmentMetrics/FeatureOverviewEnvironmentMetrics';
|
||||
|
||||
interface IStrategyIconObject {
|
||||
count: number;
|
||||
Icon: React.ReactElement;
|
||||
name: string;
|
||||
}
|
||||
interface IFeatureOverviewEnvironmentProps {
|
||||
env: IFeatureEnvironment;
|
||||
}
|
||||
@ -31,6 +45,7 @@ const FeatureOverviewEnvironment = ({
|
||||
const { projectId, featureId } = useParams<IFeatureViewParams>();
|
||||
const { metrics } = useFeatureMetrics(projectId, featureId);
|
||||
const { feature } = useFeature(projectId, featureId);
|
||||
const history = useHistory();
|
||||
|
||||
const featureMetrics = getFeatureMetrics(feature?.environments, metrics);
|
||||
const environmentMetric = featureMetrics.find(
|
||||
@ -48,6 +63,29 @@ const FeatureOverviewEnvironment = ({
|
||||
return `This environment is disabled, which means that none of your strategies are executing`;
|
||||
};
|
||||
|
||||
const strategiesLink = `/projects/${projectId}/features2/${featureId}/strategies?environment=${featureEnvironment?.name}&addStrategy=true`;
|
||||
|
||||
const getStrategyIcons = () => {
|
||||
const strategyObjects = featureEnvironment?.strategies.reduce(
|
||||
(acc, current) => {
|
||||
if (acc[current.name]) {
|
||||
acc[current.name].count = acc[current.name].count + 1;
|
||||
} else {
|
||||
acc[current.name] = {
|
||||
count: 1,
|
||||
Icon: getFeatureStrategyIcon(current.name),
|
||||
};
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as { [key: string]: IStrategyIconObject }
|
||||
);
|
||||
|
||||
return Object.keys(strategyObjects).map(strategyName => {
|
||||
return { ...strategyObjects[strategyName], name: strategyName };
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.featureOverviewEnvironment}>
|
||||
<Accordion style={{ boxShadow: 'none' }}>
|
||||
@ -55,17 +93,76 @@ const FeatureOverviewEnvironment = ({
|
||||
className={styles.accordionHeader}
|
||||
expandIcon={<ExpandMore />}
|
||||
>
|
||||
<div className={styles.headerTitle} data-loading>
|
||||
<EnvironmentIcon
|
||||
enabled={env.enabled}
|
||||
className={styles.headerIcon}
|
||||
/>
|
||||
Feature toggle execution for
|
||||
<StringTruncator
|
||||
text={env.name}
|
||||
className={styles.truncator}
|
||||
maxWidth="100"
|
||||
/>
|
||||
<div className={styles.header} data-loading>
|
||||
<div className={styles.headerTitle}>
|
||||
<EnvironmentIcon
|
||||
enabled={env.enabled}
|
||||
className={styles.headerIcon}
|
||||
/>
|
||||
Feature toggle execution for
|
||||
<StringTruncator
|
||||
text={env.name}
|
||||
className={styles.truncator}
|
||||
maxWidth="100"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.container}>
|
||||
<PermissionButton
|
||||
permission={UPDATE_FEATURE}
|
||||
onClick={() => history.push(strategiesLink)}
|
||||
className={styles.addStrategyButton}
|
||||
>
|
||||
Add strategy
|
||||
</PermissionButton>
|
||||
<span className={styles.separtor}>|</span>
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
featureEnvironment?.strategies.length !== 0
|
||||
}
|
||||
show={
|
||||
<div
|
||||
className={
|
||||
styles.stratigiesIconsContainer
|
||||
}
|
||||
>
|
||||
{getStrategyIcons()?.map(
|
||||
({ name, Icon }) => (
|
||||
<Tooltip
|
||||
title={getHumanReadableStrategyName(
|
||||
name
|
||||
)}
|
||||
arrow
|
||||
>
|
||||
<div
|
||||
className={
|
||||
styles.strategyIconContainer
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
className={
|
||||
styles.strategyIcon
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
elseShow={
|
||||
<div
|
||||
className={
|
||||
styles.noStratigiesInfoContainer
|
||||
}
|
||||
>
|
||||
<p className={styles.strategiesText}>
|
||||
No strategies defined on this toggle
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ConditionallyRender
|
||||
condition={!env.enabled}
|
||||
show={
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Link, useParams, useHistory } from 'react-router-dom';
|
||||
import { useParams, useHistory } from 'react-router-dom';
|
||||
import { IFeatureViewParams } from '../../../../../../../interfaces/params';
|
||||
import ConditionallyRender from '../../../../../../common/ConditionallyRender';
|
||||
import NoItemsStrategies from '../../../../../../common/NoItems/NoItemsStrategies/NoItemsStrategies';
|
||||
@ -6,6 +6,9 @@ import FeatureOverviewEnvironmentStrategies from '../FeatureOverviewEnvironmentS
|
||||
|
||||
import { useStyles } from '../FeatureOverviewEnvironment.styles';
|
||||
import { IFeatureEnvironment } from '../../../../../../../interfaces/featureToggle';
|
||||
import { UPDATE_FEATURE } from '../../../../../../providers/AccessProvider/permissions';
|
||||
import ResponsiveButton from '../../../../../../common/ResponsiveButton/ResponsiveButton';
|
||||
import { Add } from '@material-ui/icons';
|
||||
|
||||
interface IFeatureOverviewEnvironmentBodyProps {
|
||||
getOverviewText: () => string;
|
||||
@ -39,7 +42,14 @@ const FeatureOverviewEnvironmentBody = ({
|
||||
show={
|
||||
<>
|
||||
<div className={styles.linkContainer}>
|
||||
<Link to={strategiesLink}>Edit strategies</Link>
|
||||
<ResponsiveButton
|
||||
Icon={Add}
|
||||
onClick={() => history.push(strategiesLink)}
|
||||
maxWidth="700px"
|
||||
permission={UPDATE_FEATURE}
|
||||
>
|
||||
Add strategy
|
||||
</ResponsiveButton>
|
||||
</div>
|
||||
<FeatureOverviewEnvironmentStrategies
|
||||
strategies={featureEnvironment?.strategies}
|
||||
|
@ -1,12 +1,8 @@
|
||||
import { Warning } from '@material-ui/icons';
|
||||
import {
|
||||
IFeatureEnvironment,
|
||||
IFeatureEnvironmentMetrics,
|
||||
} from '../../../../../../../interfaces/featureToggle';
|
||||
import { calculatePercentage } from '../../../../../../../utils/calculate-percentage';
|
||||
import ConditionallyRender from '../../../../../../common/ConditionallyRender';
|
||||
import FeatureEnvironmentMetrics from '../../../FeatureEnvironmentMetrics/FeatureEnvironmentMetrics';
|
||||
|
||||
import { useStyles } from '../FeatureOverviewEnvironment.styles';
|
||||
|
||||
interface IFeatureOverviewEnvironmentFooterProps {
|
||||
@ -32,37 +28,41 @@ const FeatureOverviewEnvironmentFooter = ({
|
||||
</div>
|
||||
|
||||
<div className={styles.accordionBodyFooter}>
|
||||
<ConditionallyRender
|
||||
condition={env.enabled}
|
||||
show={
|
||||
<FeatureEnvironmentMetrics metric={environmentMetric} />
|
||||
}
|
||||
elseShow={
|
||||
<div className={styles.disabledInfo}>
|
||||
<Warning className={styles.disabledIcon} />
|
||||
<p>
|
||||
As long as the environment is disabled, all
|
||||
requests made for this feature toggle will
|
||||
return false. Add a strategy and turn on the
|
||||
environment to enable it for your users.
|
||||
</p>
|
||||
<div className={styles.resultContainer}>
|
||||
<div className={styles.dataContainer}>
|
||||
<h3 className={styles.resultTitle}>Exposure</h3>
|
||||
<div className={styles.percentageContainer}>
|
||||
{environmentMetric?.yes}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className={styles.requestContainer}>
|
||||
Total requests {totalTraffic}
|
||||
<div className={styles.percentageContainer}>
|
||||
{calculatePercentage(
|
||||
totalTraffic,
|
||||
environmentMetric?.yes
|
||||
)}
|
||||
%
|
||||
<p className={styles.requestText}>
|
||||
Total exposure of the feature in the environment in
|
||||
the last hour
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.dataContainer}>
|
||||
<h3 className={styles.resultTitle}>% exposure</h3>
|
||||
<div className={styles.percentageContainer}>
|
||||
{calculatePercentage(
|
||||
totalTraffic,
|
||||
environmentMetric?.yes
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
<p className={styles.requestText}>
|
||||
Total exposure of the feature in the environment in
|
||||
the last hour
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.dataContainer}>
|
||||
<h3 className={styles.resultTitle}>Total requests</h3>
|
||||
<div className={styles.percentageContainer}>
|
||||
{environmentMetric?.yes + environmentMetric?.no}
|
||||
</div>
|
||||
<p className={styles.requestText}>
|
||||
The total request of the feature in the environment
|
||||
in the last hour
|
||||
</p>
|
||||
</div>
|
||||
<p className={styles.requestText}>
|
||||
Received enabled for this feature in this environment in
|
||||
the last hour.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
@ -17,15 +17,18 @@ export const useStyles = makeStyles(theme => ({
|
||||
width: '75px',
|
||||
},
|
||||
infoParagraph: {
|
||||
maxWidth: '150px',
|
||||
maxWidth: '215px',
|
||||
marginTop: '0.25rem',
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
},
|
||||
percentage: {
|
||||
color: theme.palette.primary.light,
|
||||
textAlign: 'center',
|
||||
textAlign: 'right',
|
||||
fontSize: theme.fontSizes.subHeader,
|
||||
},
|
||||
percentageCircle: {
|
||||
transform: 'scale(0.85)',
|
||||
},
|
||||
[theme.breakpoints.down(700)]: {
|
||||
infoParagraph: {
|
||||
display: 'none',
|
||||
@ -35,8 +38,6 @@ export const useStyles = makeStyles(theme => ({
|
||||
icon: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
[theme.breakpoints.down(400)]: {
|
||||
percentageCircle: {
|
||||
display: 'none',
|
||||
},
|
||||
|
@ -27,7 +27,8 @@ const FeatureOverviewEnvironmentMetrics = ({
|
||||
{percentage}%
|
||||
</p>
|
||||
<p className={styles.infoParagraph} data-loading>
|
||||
No one has received this feature in the last hour.
|
||||
The feature has been requested <b>0 times</b> and
|
||||
exposed<b> 0 times</b> in the last hour
|
||||
</p>
|
||||
</div>
|
||||
<FiberManualRecord
|
||||
@ -44,8 +45,10 @@ const FeatureOverviewEnvironmentMetrics = ({
|
||||
<div className={styles.info}>
|
||||
<p className={styles.percentage}>{percentage}%</p>
|
||||
<p className={styles.infoParagraph}>
|
||||
{environmentMetric.yes} users have received the feature in
|
||||
the last hour.
|
||||
The feature has been requested{' '}
|
||||
<b>{environmentMetric.yes + environmentMetric.no} times</b>{' '}
|
||||
and exposed <b>{environmentMetric.yes} times</b> in the last
|
||||
hour
|
||||
</p>
|
||||
</div>
|
||||
<PercentageCircle
|
||||
|
@ -63,7 +63,7 @@ const FeatureStrategyExecution = ({
|
||||
return (
|
||||
<Fragment key={key}>
|
||||
<p className={styles.text}>
|
||||
{parameters[key]}% of your user base{' '}
|
||||
{parameters[key]}% of your base{' '}
|
||||
{constraints.length > 0
|
||||
? 'who match constraints'
|
||||
: ''}{' '}
|
||||
@ -146,8 +146,7 @@ const FeatureStrategyExecution = ({
|
||||
return (
|
||||
<Fragment key={param?.name}>
|
||||
<p className={styles.text}>
|
||||
{strategy?.parameters[param.name]}% of your user
|
||||
base{' '}
|
||||
{strategy?.parameters[param.name]}% of your base{' '}
|
||||
{constraints?.length > 0
|
||||
? 'who match constraints'
|
||||
: ''}{' '}
|
||||
|
@ -2112,10 +2112,10 @@
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-14.14.37.tgz"
|
||||
integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==
|
||||
|
||||
"@types/node@14.18.1":
|
||||
version "14.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.1.tgz#459886b51f52aa923dc06b9ea81cb8b1d733e9d3"
|
||||
integrity sha512-fTFWOFrgAkj737w1o0HLTIgisgYHnsZfeiqhG1Ltrf/iJjudEbUwetQAsfrtVE49JGwvpEzQR+EbMkIqG4227g==
|
||||
"@types/node@14.18.2":
|
||||
version "14.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.2.tgz#00fe4d1686d5f6cf3a2f2e9a0eef42594d06abfc"
|
||||
integrity sha512-fqtSN5xn/bBzDxMT77C1rJg6CsH/R49E7qsGuvdPJa20HtV5zSTuLJPNfnlyVH3wauKnkHdLggTVkOW/xP9oQg==
|
||||
|
||||
"@types/node@^14.14.31":
|
||||
version "14.17.19"
|
||||
@ -11265,13 +11265,14 @@ sass-loader@^10.0.5:
|
||||
schema-utils "^3.0.0"
|
||||
semver "^7.3.2"
|
||||
|
||||
sass@1.44.0:
|
||||
version "1.44.0"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.44.0.tgz#619aa0a2275c097f9af5e6b8fe8a95e3056430fb"
|
||||
integrity sha512-0hLREbHFXGQqls/K8X+koeP+ogFRPF4ZqetVB19b7Cst9Er8cOR0rc6RU7MaI4W1JmUShd1BPgPoeqmmgMMYFw==
|
||||
sass@1.45.1:
|
||||
version "1.45.1"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.45.1.tgz#fa03951f924d1ba5762949567eaf660e608a1ab0"
|
||||
integrity sha512-pwPRiq29UR0o4X3fiQyCtrESldXvUQAAE0QmcJTpsI4kuHHcLzZ54M1oNBVIXybQv8QF2zfkpFcTxp8ta97dUA==
|
||||
dependencies:
|
||||
chokidar ">=3.0.0 <4.0.0"
|
||||
immutable "^4.0.0"
|
||||
source-map-js ">=0.6.2 <2.0.0"
|
||||
|
||||
sax@~1.2.4:
|
||||
version "1.2.4"
|
||||
@ -11607,6 +11608,11 @@ source-list-map@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz"
|
||||
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
|
||||
|
||||
"source-map-js@>=0.6.2 <2.0.0":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf"
|
||||
integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==
|
||||
|
||||
source-map-js@^0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user