mirror of
https://github.com/Unleash/unleash.git
synced 2025-03-18 00:19:49 +01:00
Fix/minor 41 bugs (#329)
* fix: bigger buttons * feat: dialogue on strategies * fix: constraint errors * fix: add constraint button * fix: variant dialogue size * fix: remove commented code * fix: remove unused imports * fix: change xs to int * fix: verify constraint config before saving strategy * fix: reset error when context field is removed * fix: preserve previous state when updating * fix: disable lint for useEffect * fix: update snapshots
This commit is contained in:
parent
c33581081b
commit
e0f7a78833
@ -16,6 +16,7 @@ body {
|
||||
.MuiButton-root {
|
||||
border-radius: 3px;
|
||||
text-transform: none;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.skeleton {
|
||||
|
@ -16,8 +16,11 @@ const Dialogue = ({
|
||||
onClick,
|
||||
onClose,
|
||||
title,
|
||||
style,
|
||||
primaryButtonText,
|
||||
disabledPrimaryButton = false,
|
||||
secondaryButtonText,
|
||||
maxWidth = 'sm',
|
||||
fullWidth = false,
|
||||
}) => {
|
||||
const styles = useStyles();
|
||||
@ -28,6 +31,7 @@ const Dialogue = ({
|
||||
fullWidth={fullWidth}
|
||||
aria-labelledby={'simple-modal-title'}
|
||||
aria-describedby={'simple-modal-description'}
|
||||
maxWidth={maxWidth}
|
||||
>
|
||||
<DialogTitle className={styles.dialogTitle}>{title}</DialogTitle>
|
||||
<ConditionallyRender
|
||||
@ -48,6 +52,7 @@ const Dialogue = ({
|
||||
variant="contained"
|
||||
onClick={onClick}
|
||||
autoFocus
|
||||
disabled={disabledPrimaryButton}
|
||||
>
|
||||
{primaryButtonText || "Yes, I'm sure"}
|
||||
</Button>
|
||||
|
@ -84,7 +84,7 @@ const FeatureToggleListNew = ({
|
||||
)}
|
||||
align="left"
|
||||
>
|
||||
<span data-loading>name</span>
|
||||
<span data-loading>Name</span>
|
||||
</TableCell>
|
||||
<TableCell
|
||||
className={classnames(
|
||||
@ -94,7 +94,7 @@ const FeatureToggleListNew = ({
|
||||
)}
|
||||
align="left"
|
||||
>
|
||||
<span data-loading>type</span>
|
||||
<span data-loading>Type</span>
|
||||
</TableCell>
|
||||
{getEnvironments().map((env: any) => {
|
||||
return (
|
||||
@ -109,7 +109,7 @@ const FeatureToggleListNew = ({
|
||||
>
|
||||
<span data-loading>
|
||||
{env.name === ':global:'
|
||||
? 'status'
|
||||
? 'Status'
|
||||
: env.name}
|
||||
</span>
|
||||
</TableCell>
|
||||
|
@ -1,19 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
DialogActions,
|
||||
Typography,
|
||||
} from '@material-ui/core';
|
||||
import { Typography } from '@material-ui/core';
|
||||
|
||||
import CreateStrategyCard from './AddStrategyCard/AddStrategyCard';
|
||||
import { useStyles } from './AddStrategy.styles';
|
||||
import ConditionallyRender from '../../../common/ConditionallyRender';
|
||||
import { resolveDefaultParamValue } from './utils';
|
||||
import { getHumanReadbleStrategy } from '../../../../utils/strategy-names';
|
||||
import Dialogue from '../../../common/Dialogue';
|
||||
|
||||
const AddStrategy = ({
|
||||
strategies,
|
||||
@ -98,49 +91,39 @@ const AddStrategy = ({
|
||||
));
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
<Dialogue
|
||||
open={showCreateStrategy}
|
||||
title="Add a new strategy"
|
||||
aria-labelledby="form-dialog-title"
|
||||
fullWidth
|
||||
onClose={() => setShowCreateStrategy(false)}
|
||||
secondaryButtonText="Cancel"
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle id="form-dialog-title">Add a new strategy</DialogTitle>
|
||||
<Typography variant="subtitle1" className={styles.subTitle}>
|
||||
Built in strategies
|
||||
</Typography>
|
||||
<div className={styles.createStrategyCardContainer}>
|
||||
{renderBuiltInStrategies()}
|
||||
</div>
|
||||
|
||||
<DialogContent>
|
||||
<Typography variant="subtitle1" className={styles.subTitle}>
|
||||
Built in strategies
|
||||
</Typography>
|
||||
<div className={styles.createStrategyCardContainer}>
|
||||
{renderBuiltInStrategies()}
|
||||
</div>
|
||||
|
||||
<ConditionallyRender
|
||||
condition={customStrategies.length > 0}
|
||||
show={
|
||||
<>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
className={styles.subTitle}
|
||||
>
|
||||
Custom strategies
|
||||
</Typography>
|
||||
<div className={styles.createStrategyCardContainer}>
|
||||
{renderCustomStrategies()}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions>
|
||||
<Button
|
||||
color="secondary"
|
||||
onClick={() => setShowCreateStrategy(false)}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
<ConditionallyRender
|
||||
condition={customStrategies.length > 0}
|
||||
show={
|
||||
<>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
className={styles.subTitle}
|
||||
>
|
||||
Custom strategies
|
||||
</Typography>
|
||||
<div className={styles.createStrategyCardContainer}>
|
||||
{renderCustomStrategies()}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Dialogue>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,12 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
DialogActions,
|
||||
} from '@material-ui/core';
|
||||
|
||||
import FlexibleStrategy from './FlexibleStrategy';
|
||||
import DefaultStrategy from './default-strategy';
|
||||
@ -15,6 +8,7 @@ import GeneralStrategy from './general-strategy';
|
||||
import StrategyConstraints from '../StrategyConstraint/StrategyConstraintInput';
|
||||
|
||||
import { getHumanReadbleStrategyName } from '../../../../utils/strategy-names';
|
||||
import Dialogue from '../../../common/Dialogue';
|
||||
|
||||
const EditStrategyModal = ({
|
||||
onCancel,
|
||||
@ -24,6 +18,8 @@ const EditStrategyModal = ({
|
||||
strategyDefinition,
|
||||
context,
|
||||
}) => {
|
||||
const [constraintError, setConstraintError] = useState({});
|
||||
|
||||
const updateParameters = parameters => {
|
||||
const updatedStrategy = { ...strategy, parameters };
|
||||
updateStrategy(updatedStrategy);
|
||||
@ -57,47 +53,66 @@ const EditStrategyModal = ({
|
||||
|
||||
const { parameters } = strategy;
|
||||
|
||||
const disabledPrimaryButton = Object.keys(constraintError).some(key => {
|
||||
return constraintError[key];
|
||||
});
|
||||
|
||||
const save = () => {
|
||||
const { constraints } = strategy;
|
||||
let valid = true;
|
||||
|
||||
constraints.forEach((constraint, index) => {
|
||||
const { values } = constraint;
|
||||
|
||||
if (values.length === 0) {
|
||||
setConstraintError(prev => ({
|
||||
...prev,
|
||||
[`${constraint.contextName}-${index}`]:
|
||||
'You need to specify at least one value',
|
||||
}));
|
||||
valid = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (valid) {
|
||||
saveStrategy();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
<Dialogue
|
||||
open={!!strategy}
|
||||
aria-labelledby="form-dialog-title"
|
||||
fullWidth
|
||||
onClose={onCancel}
|
||||
onClick={save}
|
||||
title={`Configure ${getHumanReadbleStrategyName(
|
||||
strategy.name
|
||||
)} strategy`}
|
||||
primaryButtonText="Save"
|
||||
secondaryButtonText="Cancel"
|
||||
maxWidth="md"
|
||||
disabledPrimaryButton={disabledPrimaryButton}
|
||||
>
|
||||
<DialogTitle id="form-dialog-title">
|
||||
Configure {getHumanReadbleStrategyName(strategy.name)} strategy
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<div>
|
||||
<StrategyConstraints
|
||||
updateConstraints={updateConstraints}
|
||||
constraints={strategy.constraints || []}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<Type
|
||||
parameters={parameters}
|
||||
updateParameter={updateParameter}
|
||||
strategyDefinition={strategyDefinition}
|
||||
editable
|
||||
context={context}
|
||||
<div>
|
||||
<StrategyConstraints
|
||||
updateConstraints={updateConstraints}
|
||||
constraints={strategy.constraints || []}
|
||||
constraintError={constraintError}
|
||||
setConstraintError={setConstraintError}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onCancel} color="secondary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={saveStrategy}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<Type
|
||||
parameters={parameters}
|
||||
updateParameter={updateParameter}
|
||||
strategyDefinition={strategyDefinition}
|
||||
editable
|
||||
context={context}
|
||||
/>
|
||||
</Dialogue>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Tooltip, Typography } from '@material-ui/core';
|
||||
import { Button, Tooltip, Typography } from '@material-ui/core';
|
||||
import { Info } from '@material-ui/icons';
|
||||
|
||||
import StrategyConstraintInputField from '../StrategyConstraintInputField';
|
||||
@ -12,6 +12,8 @@ const StrategyConstraintInput = ({
|
||||
contextNames,
|
||||
contextFields,
|
||||
enabled,
|
||||
constraintError,
|
||||
setConstraintError,
|
||||
}) => {
|
||||
const commonStyles = useCommonStyles();
|
||||
const addConstraint = evt => {
|
||||
@ -71,18 +73,21 @@ const StrategyConstraintInput = ({
|
||||
contextFields={contextFields}
|
||||
updateConstraint={updateConstraint(index)}
|
||||
removeConstraint={removeConstraint(index)}
|
||||
constraintError={constraintError}
|
||||
setConstraintError={setConstraintError}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<small>
|
||||
<a
|
||||
href="#add-constraint"
|
||||
<Button
|
||||
title="Add constraint"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={addConstraint}
|
||||
>
|
||||
Add constraint
|
||||
</a>
|
||||
</Button>
|
||||
</small>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { IconButton, TextField } from '@material-ui/core';
|
||||
import { Autocomplete } from '@material-ui/lab';
|
||||
@ -20,27 +20,47 @@ const StrategyConstraintInputField = ({
|
||||
updateConstraint,
|
||||
removeConstraint,
|
||||
contextFields,
|
||||
id,
|
||||
constraintError,
|
||||
setConstraintError,
|
||||
}) => {
|
||||
const [error, setError] = useState();
|
||||
const commonStyles = useCommonStyles();
|
||||
const styles = useStyles();
|
||||
const onBlur = evt => {
|
||||
evt.preventDefault();
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
resetError();
|
||||
};
|
||||
/*eslint-disable-next-line */
|
||||
}, []);
|
||||
|
||||
const checkError = () => {
|
||||
const values = constraint.values;
|
||||
const filtered = values.filter(v => v).map(v => v.trim());
|
||||
if (filtered.length !== values.length) {
|
||||
updateConstraint(filtered, 'values');
|
||||
}
|
||||
if (filtered.length === 0) {
|
||||
setError('You need to specify at least one value');
|
||||
setConstraintError(prev => ({
|
||||
...prev,
|
||||
[id]: 'You need to specify at least one value',
|
||||
}));
|
||||
} else {
|
||||
setError(undefined);
|
||||
resetError();
|
||||
}
|
||||
};
|
||||
|
||||
const resetError = () =>
|
||||
setConstraintError(prev => ({ ...prev, [id]: undefined }));
|
||||
|
||||
const commonStyles = useCommonStyles();
|
||||
const styles = useStyles();
|
||||
const onBlur = evt => {
|
||||
evt.preventDefault();
|
||||
checkError();
|
||||
};
|
||||
|
||||
const handleChangeValue = selectedOptions => {
|
||||
const values = selectedOptions ? selectedOptions.map(o => o.value) : [];
|
||||
updateConstraint(values, 'values');
|
||||
checkError();
|
||||
};
|
||||
|
||||
const constraintContextNames = contextFields.map(f => ({
|
||||
@ -59,9 +79,11 @@ const StrategyConstraintInputField = ({
|
||||
: undefined;
|
||||
const values = constraint.values.map(v => ({ value: v, label: v }));
|
||||
|
||||
const error = constraintError[id];
|
||||
|
||||
return (
|
||||
<tr className={commonStyles.contentSpacingY}>
|
||||
<td>
|
||||
<td className={styles.tableCell}>
|
||||
<MySelect
|
||||
name="contextName"
|
||||
label="Context Field"
|
||||
@ -73,7 +95,7 @@ const StrategyConstraintInputField = ({
|
||||
className={styles.contextField}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<td className={styles.tableCell}>
|
||||
<MySelect
|
||||
name="operator"
|
||||
label="Operator"
|
||||
@ -85,52 +107,74 @@ const StrategyConstraintInputField = ({
|
||||
className={styles.operator}
|
||||
/>
|
||||
</td>
|
||||
<td style={{ width: '100%' }}>
|
||||
<td className={styles.tableCell} style={{ width: '100%' }}>
|
||||
<ConditionallyRender
|
||||
condition={options}
|
||||
show={
|
||||
<Autocomplete
|
||||
multiple
|
||||
size="small"
|
||||
options={options}
|
||||
value={values || []}
|
||||
getOptionLabel={option => option.label}
|
||||
getOptionSelected={(option, value) =>
|
||||
option.value === value.value
|
||||
}
|
||||
filterSelectedOptions
|
||||
filterOptions={options =>
|
||||
options.filter(
|
||||
o => !values.some(v => v.value === o.value)
|
||||
)
|
||||
}
|
||||
onChange={(evt, values) =>
|
||||
handleChangeValue(values)
|
||||
}
|
||||
renderInput={params => (
|
||||
<TextField
|
||||
{...params}
|
||||
variant="outlined"
|
||||
label="Values"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<div className={styles.inputContainer}>
|
||||
<Autocomplete
|
||||
multiple
|
||||
size="small"
|
||||
options={options}
|
||||
value={values || []}
|
||||
getOptionLabel={option => option.label}
|
||||
onBlur={onBlur}
|
||||
onFocus={() => resetError()}
|
||||
getOptionSelected={(option, value) =>
|
||||
option.value === value.value
|
||||
}
|
||||
filterSelectedOptions
|
||||
filterOptions={options =>
|
||||
options.filter(
|
||||
o =>
|
||||
!values.some(
|
||||
v => v.value === o.value
|
||||
)
|
||||
)
|
||||
}
|
||||
onChange={(evt, values) =>
|
||||
handleChangeValue(values)
|
||||
}
|
||||
renderInput={params => (
|
||||
<TextField
|
||||
{...params}
|
||||
variant="outlined"
|
||||
label={'Values'}
|
||||
error={Boolean(error)}
|
||||
helperText={error}
|
||||
FormHelperTextProps={{
|
||||
classes: {
|
||||
root: styles.helperText,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
elseShow={
|
||||
<InputListField
|
||||
name="values"
|
||||
error={error}
|
||||
onBlur={onBlur}
|
||||
values={constraint.values}
|
||||
label="Values (v1, v2, v3)"
|
||||
updateValues={values =>
|
||||
updateConstraint(values, 'values')
|
||||
}
|
||||
/>
|
||||
<div className={styles.inputContainer}>
|
||||
<InputListField
|
||||
name="values"
|
||||
error={Boolean(error)}
|
||||
onBlur={onBlur}
|
||||
values={constraint.values}
|
||||
label="Values (v1, v2, v3)"
|
||||
updateValues={values =>
|
||||
updateConstraint(values, 'values')
|
||||
}
|
||||
helperText={error}
|
||||
FormHelperTextProps={{
|
||||
classes: {
|
||||
root: styles.helperText,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<td className={styles.tableCell}>
|
||||
<IconButton onClick={removeConstraint}>
|
||||
<Delete />
|
||||
</IconButton>
|
||||
|
@ -7,4 +7,21 @@ export const useStyles = makeStyles({
|
||||
operator: {
|
||||
minWidth: '105px',
|
||||
},
|
||||
inputContainer: {
|
||||
position: 'relative',
|
||||
},
|
||||
inputError: {
|
||||
position: 'absolute',
|
||||
fontSize: '0.9rem',
|
||||
color: 'red',
|
||||
top: '10px',
|
||||
left: '12px',
|
||||
},
|
||||
tableCell: {
|
||||
paddingBottom: '1.25rem',
|
||||
},
|
||||
helperText: {
|
||||
position: 'absolute',
|
||||
top: '35px',
|
||||
},
|
||||
});
|
||||
|
@ -187,6 +187,8 @@ const AddVariant = ({
|
||||
primaryButtonText="Save"
|
||||
secondaryButtonText="Cancel"
|
||||
title={title}
|
||||
fullWidth
|
||||
maxWidth="md"
|
||||
>
|
||||
<form onSubmit={submit} className={commonStyles.contentSpacingY}>
|
||||
<p style={{ color: 'red' }}>{error.general}</p>
|
||||
@ -195,6 +197,7 @@ const AddVariant = ({
|
||||
name="name"
|
||||
placeholder=""
|
||||
className={commonStyles.fullWidth}
|
||||
style={{ maxWidth: '350px' }}
|
||||
helperText={error.name}
|
||||
value={data.name || ''}
|
||||
error={Boolean(error.name)}
|
||||
@ -250,11 +253,17 @@ const AddVariant = ({
|
||||
title="Passed to the variant object. Can be anything
|
||||
(json, value, csv)"
|
||||
>
|
||||
<Info style={{ width: '18.5px', height: '18.5px' }} />
|
||||
<Info
|
||||
style={{
|
||||
width: '18.5px',
|
||||
height: '18.5px',
|
||||
color: 'grey',
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</p>
|
||||
<Grid container>
|
||||
<Grid item md={3}>
|
||||
<Grid item md={2} sm={2} xs={4}>
|
||||
<MySelect
|
||||
name="type"
|
||||
label="Type"
|
||||
@ -262,10 +271,10 @@ const AddVariant = ({
|
||||
value={payload.type}
|
||||
options={payloadOptions}
|
||||
onChange={onPayload}
|
||||
style={{ minWidth: '100px' }}
|
||||
style={{ minWidth: '100px', width: '100%' }}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item md={9}>
|
||||
<Grid item md={8} sm={8} xs={6}>
|
||||
<TextField
|
||||
rows={1}
|
||||
label="Value"
|
||||
@ -281,13 +290,14 @@ const AddVariant = ({
|
||||
<ConditionallyRender
|
||||
condition={overrides.length > 0}
|
||||
show={
|
||||
<p style={{ marginBottom: '.5rem' }}>
|
||||
<p style={{ marginBottom: '1rem' }}>
|
||||
<strong>Overrides </strong>
|
||||
<Tooltip title="Here you can specify which users should get this variant.">
|
||||
<Info
|
||||
style={{
|
||||
width: '18.5px',
|
||||
height: '18.5px',
|
||||
color: 'grey',
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
@ -301,7 +311,13 @@ const AddVariant = ({
|
||||
updateOverrideValues={updateOverrideValues}
|
||||
updateValues={updateOverrideValues}
|
||||
/>
|
||||
<Button onClick={onAddOverride}>Add override</Button>{' '}
|
||||
<Button
|
||||
onClick={onAddOverride}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
Add override
|
||||
</Button>{' '}
|
||||
</form>
|
||||
</Dialog>
|
||||
);
|
||||
|
@ -41,7 +41,13 @@ const OverrideConfig = ({
|
||||
|
||||
return (
|
||||
<Grid container key={`override=${i}`} alignItems="center">
|
||||
<Grid item md={3} className={styles.contextFieldSelect}>
|
||||
<Grid
|
||||
item
|
||||
md={3}
|
||||
sm={3}
|
||||
xs={3}
|
||||
className={styles.contextFieldSelect}
|
||||
>
|
||||
<MySelect
|
||||
name="contextName"
|
||||
label="Context Field"
|
||||
@ -53,7 +59,7 @@ const OverrideConfig = ({
|
||||
onChange={updateOverrideType(i)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid md={7} item>
|
||||
<Grid md={7} sm={7} xs={6} item>
|
||||
<ConditionallyRender
|
||||
condition={legalValues && legalValues.length > 0}
|
||||
show={
|
||||
@ -68,6 +74,7 @@ const OverrideConfig = ({
|
||||
getOptionLabel={option => option}
|
||||
defaultValue={o.values}
|
||||
value={o.values}
|
||||
style={{ width: '100%' }}
|
||||
filterSelectedOptions
|
||||
size="small"
|
||||
renderInput={params => (
|
||||
@ -75,6 +82,7 @@ const OverrideConfig = ({
|
||||
{...params}
|
||||
variant="outlined"
|
||||
label="Legal values"
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
@ -16,255 +16,253 @@ export const Footer = () => {
|
||||
<Grid item md={4} xs={12}>
|
||||
<ShowApiDetailsContainer />
|
||||
</Grid>
|
||||
<Grid item xs="12" md="auto">
|
||||
<Grid container spacing={7} direction="row" >
|
||||
<Grid item>
|
||||
<section title="Unleash SDK">
|
||||
<h4>Server SDKs</h4>
|
||||
<List className={styles.list} dense>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/node_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Node.js
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/java_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Java
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/go_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Go
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>{' '}
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/ruby_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Ruby
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>{' '}
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/python_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Python
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/dot_net_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
.NET
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/php_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
PHP
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
All SDKs
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</section>
|
||||
</Grid>
|
||||
<Grid item justifyContent="center">
|
||||
<section title="Unleash SDK">
|
||||
<h4>Frontend SDKs</h4>
|
||||
<List className={styles.list} dense>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/unleash-proxy"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Unleash Proxy
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/proxy-javascript"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
JavaScript SDK
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/proxy-react"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
React SDK
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/proxy-ios"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
iOS SDK
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/android_proxy_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Android SDK
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</section>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<section>
|
||||
<h4>About</h4>
|
||||
<List className={styles.list} dense>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://www.getunleash.io/"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
getunleash.io
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://twitter.com/getunleash"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Twitter
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://www.linkedin.com/company/getunleash"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
LinkedIn
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://github.com/Unleash/unleash"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</section>
|
||||
<Grid item xs={12} md="auto">
|
||||
<Grid container spacing={7} direction="row">
|
||||
<Grid item>
|
||||
<section title="Unleash SDK">
|
||||
<h4>Server SDKs</h4>
|
||||
<List className={styles.list} dense>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/node_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Node.js
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/java_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Java
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/go_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Go
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>{' '}
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/ruby_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Ruby
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>{' '}
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/python_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Python
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/dot_net_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
.NET
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/php_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
PHP
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
All SDKs
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</section>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<section title="Unleash SDK">
|
||||
<h4>Frontend SDKs</h4>
|
||||
<List className={styles.list} dense>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/unleash-proxy"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Unleash Proxy
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/proxy-javascript"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
JavaScript SDK
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/proxy-react"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
React SDK
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/proxy-ios"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
iOS SDK
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://docs.getunleash.io/sdks/android_proxy_sdk"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Android SDK
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</section>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<section>
|
||||
<h4>About</h4>
|
||||
<List className={styles.list} dense>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://www.getunleash.io/"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
getunleash.io
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://twitter.com/getunleash"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
Twitter
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://www.linkedin.com/company/getunleash"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
LinkedIn
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem className={styles.listItem}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<a
|
||||
href="https://github.com/Unleash/unleash"
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</section>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
@ -199,7 +199,6 @@ exports[`should render DrawerMenu 1`] = `
|
||||
</div>
|
||||
<div
|
||||
className="MuiGrid-root MuiGrid-item"
|
||||
justifyContent="center"
|
||||
>
|
||||
<section
|
||||
title="Unleash SDK"
|
||||
@ -602,7 +601,6 @@ exports[`should render DrawerMenu with "features" selected 1`] = `
|
||||
</div>
|
||||
<div
|
||||
className="MuiGrid-root MuiGrid-item"
|
||||
justifyContent="center"
|
||||
>
|
||||
<section
|
||||
title="Unleash SDK"
|
||||
|
Loading…
Reference in New Issue
Block a user