1
0
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:
Fredrik Strand Oseberg 2021-08-27 13:18:11 +02:00 committed by GitHub
parent c33581081b
commit e0f7a78833
12 changed files with 491 additions and 401 deletions

View File

@ -16,6 +16,7 @@ body {
.MuiButton-root { .MuiButton-root {
border-radius: 3px; border-radius: 3px;
text-transform: none; text-transform: none;
font-size: 16px;
} }
.skeleton { .skeleton {

View File

@ -16,8 +16,11 @@ const Dialogue = ({
onClick, onClick,
onClose, onClose,
title, title,
style,
primaryButtonText, primaryButtonText,
disabledPrimaryButton = false,
secondaryButtonText, secondaryButtonText,
maxWidth = 'sm',
fullWidth = false, fullWidth = false,
}) => { }) => {
const styles = useStyles(); const styles = useStyles();
@ -28,6 +31,7 @@ const Dialogue = ({
fullWidth={fullWidth} fullWidth={fullWidth}
aria-labelledby={'simple-modal-title'} aria-labelledby={'simple-modal-title'}
aria-describedby={'simple-modal-description'} aria-describedby={'simple-modal-description'}
maxWidth={maxWidth}
> >
<DialogTitle className={styles.dialogTitle}>{title}</DialogTitle> <DialogTitle className={styles.dialogTitle}>{title}</DialogTitle>
<ConditionallyRender <ConditionallyRender
@ -48,6 +52,7 @@ const Dialogue = ({
variant="contained" variant="contained"
onClick={onClick} onClick={onClick}
autoFocus autoFocus
disabled={disabledPrimaryButton}
> >
{primaryButtonText || "Yes, I'm sure"} {primaryButtonText || "Yes, I'm sure"}
</Button> </Button>

View File

@ -84,7 +84,7 @@ const FeatureToggleListNew = ({
)} )}
align="left" align="left"
> >
<span data-loading>name</span> <span data-loading>Name</span>
</TableCell> </TableCell>
<TableCell <TableCell
className={classnames( className={classnames(
@ -94,7 +94,7 @@ const FeatureToggleListNew = ({
)} )}
align="left" align="left"
> >
<span data-loading>type</span> <span data-loading>Type</span>
</TableCell> </TableCell>
{getEnvironments().map((env: any) => { {getEnvironments().map((env: any) => {
return ( return (
@ -109,7 +109,7 @@ const FeatureToggleListNew = ({
> >
<span data-loading> <span data-loading>
{env.name === ':global:' {env.name === ':global:'
? 'status' ? 'Status'
: env.name} : env.name}
</span> </span>
</TableCell> </TableCell>

View File

@ -1,19 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import { Typography } from '@material-ui/core';
Button,
Dialog,
DialogContent,
DialogTitle,
DialogActions,
Typography,
} from '@material-ui/core';
import CreateStrategyCard from './AddStrategyCard/AddStrategyCard'; import CreateStrategyCard from './AddStrategyCard/AddStrategyCard';
import { useStyles } from './AddStrategy.styles'; import { useStyles } from './AddStrategy.styles';
import ConditionallyRender from '../../../common/ConditionallyRender'; import ConditionallyRender from '../../../common/ConditionallyRender';
import { resolveDefaultParamValue } from './utils'; import { resolveDefaultParamValue } from './utils';
import { getHumanReadbleStrategy } from '../../../../utils/strategy-names'; import { getHumanReadbleStrategy } from '../../../../utils/strategy-names';
import Dialogue from '../../../common/Dialogue';
const AddStrategy = ({ const AddStrategy = ({
strategies, strategies,
@ -98,49 +91,39 @@ const AddStrategy = ({
)); ));
return ( return (
<Dialog <Dialogue
open={showCreateStrategy} open={showCreateStrategy}
title="Add a new strategy"
aria-labelledby="form-dialog-title" aria-labelledby="form-dialog-title"
fullWidth onClose={() => setShowCreateStrategy(false)}
secondaryButtonText="Cancel"
maxWidth="md" 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> <ConditionallyRender
<Typography variant="subtitle1" className={styles.subTitle}> condition={customStrategies.length > 0}
Built in strategies show={
</Typography> <>
<div className={styles.createStrategyCardContainer}> <Typography
{renderBuiltInStrategies()} variant="subtitle1"
</div> className={styles.subTitle}
>
<ConditionallyRender Custom strategies
condition={customStrategies.length > 0} </Typography>
show={ <div className={styles.createStrategyCardContainer}>
<> {renderCustomStrategies()}
<Typography </div>
variant="subtitle1" </>
className={styles.subTitle} }
> />
Custom strategies </Dialogue>
</Typography>
<div className={styles.createStrategyCardContainer}>
{renderCustomStrategies()}
</div>
</>
}
/>
</DialogContent>
<DialogActions>
<Button
color="secondary"
onClick={() => setShowCreateStrategy(false)}
>
Cancel
</Button>
</DialogActions>
</Dialog>
); );
}; };

View File

@ -1,12 +1,5 @@
import React from 'react'; import { useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {
Button,
Dialog,
DialogContent,
DialogTitle,
DialogActions,
} from '@material-ui/core';
import FlexibleStrategy from './FlexibleStrategy'; import FlexibleStrategy from './FlexibleStrategy';
import DefaultStrategy from './default-strategy'; import DefaultStrategy from './default-strategy';
@ -15,6 +8,7 @@ import GeneralStrategy from './general-strategy';
import StrategyConstraints from '../StrategyConstraint/StrategyConstraintInput'; import StrategyConstraints from '../StrategyConstraint/StrategyConstraintInput';
import { getHumanReadbleStrategyName } from '../../../../utils/strategy-names'; import { getHumanReadbleStrategyName } from '../../../../utils/strategy-names';
import Dialogue from '../../../common/Dialogue';
const EditStrategyModal = ({ const EditStrategyModal = ({
onCancel, onCancel,
@ -24,6 +18,8 @@ const EditStrategyModal = ({
strategyDefinition, strategyDefinition,
context, context,
}) => { }) => {
const [constraintError, setConstraintError] = useState({});
const updateParameters = parameters => { const updateParameters = parameters => {
const updatedStrategy = { ...strategy, parameters }; const updatedStrategy = { ...strategy, parameters };
updateStrategy(updatedStrategy); updateStrategy(updatedStrategy);
@ -57,47 +53,66 @@ const EditStrategyModal = ({
const { parameters } = strategy; 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 ( return (
<Dialog <Dialogue
open={!!strategy} open={!!strategy}
aria-labelledby="form-dialog-title" aria-labelledby="form-dialog-title"
fullWidth fullWidth
onClose={onCancel}
onClick={save}
title={`Configure ${getHumanReadbleStrategyName(
strategy.name
)} strategy`}
primaryButtonText="Save"
secondaryButtonText="Cancel"
maxWidth="md" maxWidth="md"
disabledPrimaryButton={disabledPrimaryButton}
> >
<DialogTitle id="form-dialog-title"> <div>
Configure {getHumanReadbleStrategyName(strategy.name)} strategy <StrategyConstraints
</DialogTitle> updateConstraints={updateConstraints}
<DialogContent> constraints={strategy.constraints || []}
<div> constraintError={constraintError}
<StrategyConstraints setConstraintError={setConstraintError}
updateConstraints={updateConstraints}
constraints={strategy.constraints || []}
/>
</div>
<br />
<br />
<Type
parameters={parameters}
updateParameter={updateParameter}
strategyDefinition={strategyDefinition}
editable
context={context}
/> />
</DialogContent> </div>
<DialogActions>
<Button onClick={onCancel} color="secondary"> <br />
Cancel <br />
</Button> <Type
<Button parameters={parameters}
onClick={saveStrategy} updateParameter={updateParameter}
color="primary" strategyDefinition={strategyDefinition}
variant="contained" editable
> context={context}
Save />
</Button> </Dialogue>
</DialogActions>
</Dialog>
); );
}; };

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; 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 { Info } from '@material-ui/icons';
import StrategyConstraintInputField from '../StrategyConstraintInputField'; import StrategyConstraintInputField from '../StrategyConstraintInputField';
@ -12,6 +12,8 @@ const StrategyConstraintInput = ({
contextNames, contextNames,
contextFields, contextFields,
enabled, enabled,
constraintError,
setConstraintError,
}) => { }) => {
const commonStyles = useCommonStyles(); const commonStyles = useCommonStyles();
const addConstraint = evt => { const addConstraint = evt => {
@ -71,18 +73,21 @@ const StrategyConstraintInput = ({
contextFields={contextFields} contextFields={contextFields}
updateConstraint={updateConstraint(index)} updateConstraint={updateConstraint(index)}
removeConstraint={removeConstraint(index)} removeConstraint={removeConstraint(index)}
constraintError={constraintError}
setConstraintError={setConstraintError}
/> />
))} ))}
</tbody> </tbody>
</table> </table>
<small> <small>
<a <Button
href="#add-constraint"
title="Add constraint" title="Add constraint"
variant="contained"
color="primary"
onClick={addConstraint} onClick={addConstraint}
> >
Add constraint Add constraint
</a> </Button>
</small> </small>
</div> </div>
); );

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import { useEffect } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { IconButton, TextField } from '@material-ui/core'; import { IconButton, TextField } from '@material-ui/core';
import { Autocomplete } from '@material-ui/lab'; import { Autocomplete } from '@material-ui/lab';
@ -20,27 +20,47 @@ const StrategyConstraintInputField = ({
updateConstraint, updateConstraint,
removeConstraint, removeConstraint,
contextFields, contextFields,
id,
constraintError,
setConstraintError,
}) => { }) => {
const [error, setError] = useState(); useEffect(() => {
const commonStyles = useCommonStyles(); return () => {
const styles = useStyles(); resetError();
const onBlur = evt => { };
evt.preventDefault(); /*eslint-disable-next-line */
}, []);
const checkError = () => {
const values = constraint.values; const values = constraint.values;
const filtered = values.filter(v => v).map(v => v.trim()); const filtered = values.filter(v => v).map(v => v.trim());
if (filtered.length !== values.length) { if (filtered.length !== values.length) {
updateConstraint(filtered, 'values'); updateConstraint(filtered, 'values');
} }
if (filtered.length === 0) { 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 { } 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 handleChangeValue = selectedOptions => {
const values = selectedOptions ? selectedOptions.map(o => o.value) : []; const values = selectedOptions ? selectedOptions.map(o => o.value) : [];
updateConstraint(values, 'values'); updateConstraint(values, 'values');
checkError();
}; };
const constraintContextNames = contextFields.map(f => ({ const constraintContextNames = contextFields.map(f => ({
@ -59,9 +79,11 @@ const StrategyConstraintInputField = ({
: undefined; : undefined;
const values = constraint.values.map(v => ({ value: v, label: v })); const values = constraint.values.map(v => ({ value: v, label: v }));
const error = constraintError[id];
return ( return (
<tr className={commonStyles.contentSpacingY}> <tr className={commonStyles.contentSpacingY}>
<td> <td className={styles.tableCell}>
<MySelect <MySelect
name="contextName" name="contextName"
label="Context Field" label="Context Field"
@ -73,7 +95,7 @@ const StrategyConstraintInputField = ({
className={styles.contextField} className={styles.contextField}
/> />
</td> </td>
<td> <td className={styles.tableCell}>
<MySelect <MySelect
name="operator" name="operator"
label="Operator" label="Operator"
@ -85,52 +107,74 @@ const StrategyConstraintInputField = ({
className={styles.operator} className={styles.operator}
/> />
</td> </td>
<td style={{ width: '100%' }}> <td className={styles.tableCell} style={{ width: '100%' }}>
<ConditionallyRender <ConditionallyRender
condition={options} condition={options}
show={ show={
<Autocomplete <div className={styles.inputContainer}>
multiple <Autocomplete
size="small" multiple
options={options} size="small"
value={values || []} options={options}
getOptionLabel={option => option.label} value={values || []}
getOptionSelected={(option, value) => getOptionLabel={option => option.label}
option.value === value.value onBlur={onBlur}
} onFocus={() => resetError()}
filterSelectedOptions getOptionSelected={(option, value) =>
filterOptions={options => option.value === value.value
options.filter( }
o => !values.some(v => v.value === o.value) filterSelectedOptions
) filterOptions={options =>
} options.filter(
onChange={(evt, values) => o =>
handleChangeValue(values) !values.some(
} v => v.value === o.value
renderInput={params => ( )
<TextField )
{...params} }
variant="outlined" onChange={(evt, values) =>
label="Values" handleChangeValue(values)
/> }
)} renderInput={params => (
/> <TextField
{...params}
variant="outlined"
label={'Values'}
error={Boolean(error)}
helperText={error}
FormHelperTextProps={{
classes: {
root: styles.helperText,
},
}}
/>
)}
/>
</div>
} }
elseShow={ elseShow={
<InputListField <div className={styles.inputContainer}>
name="values" <InputListField
error={error} name="values"
onBlur={onBlur} error={Boolean(error)}
values={constraint.values} onBlur={onBlur}
label="Values (v1, v2, v3)" values={constraint.values}
updateValues={values => label="Values (v1, v2, v3)"
updateConstraint(values, 'values') updateValues={values =>
} updateConstraint(values, 'values')
/> }
helperText={error}
FormHelperTextProps={{
classes: {
root: styles.helperText,
},
}}
/>
</div>
} }
/> />
</td> </td>
<td> <td className={styles.tableCell}>
<IconButton onClick={removeConstraint}> <IconButton onClick={removeConstraint}>
<Delete /> <Delete />
</IconButton> </IconButton>

View File

@ -7,4 +7,21 @@ export const useStyles = makeStyles({
operator: { operator: {
minWidth: '105px', 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',
},
}); });

View File

@ -187,6 +187,8 @@ const AddVariant = ({
primaryButtonText="Save" primaryButtonText="Save"
secondaryButtonText="Cancel" secondaryButtonText="Cancel"
title={title} title={title}
fullWidth
maxWidth="md"
> >
<form onSubmit={submit} className={commonStyles.contentSpacingY}> <form onSubmit={submit} className={commonStyles.contentSpacingY}>
<p style={{ color: 'red' }}>{error.general}</p> <p style={{ color: 'red' }}>{error.general}</p>
@ -195,6 +197,7 @@ const AddVariant = ({
name="name" name="name"
placeholder="" placeholder=""
className={commonStyles.fullWidth} className={commonStyles.fullWidth}
style={{ maxWidth: '350px' }}
helperText={error.name} helperText={error.name}
value={data.name || ''} value={data.name || ''}
error={Boolean(error.name)} error={Boolean(error.name)}
@ -250,11 +253,17 @@ const AddVariant = ({
title="Passed to the variant object. Can be anything title="Passed to the variant object. Can be anything
(json, value, csv)" (json, value, csv)"
> >
<Info style={{ width: '18.5px', height: '18.5px' }} /> <Info
style={{
width: '18.5px',
height: '18.5px',
color: 'grey',
}}
/>
</Tooltip> </Tooltip>
</p> </p>
<Grid container> <Grid container>
<Grid item md={3}> <Grid item md={2} sm={2} xs={4}>
<MySelect <MySelect
name="type" name="type"
label="Type" label="Type"
@ -262,10 +271,10 @@ const AddVariant = ({
value={payload.type} value={payload.type}
options={payloadOptions} options={payloadOptions}
onChange={onPayload} onChange={onPayload}
style={{ minWidth: '100px' }} style={{ minWidth: '100px', width: '100%' }}
/> />
</Grid> </Grid>
<Grid item md={9}> <Grid item md={8} sm={8} xs={6}>
<TextField <TextField
rows={1} rows={1}
label="Value" label="Value"
@ -281,13 +290,14 @@ const AddVariant = ({
<ConditionallyRender <ConditionallyRender
condition={overrides.length > 0} condition={overrides.length > 0}
show={ show={
<p style={{ marginBottom: '.5rem' }}> <p style={{ marginBottom: '1rem' }}>
<strong>Overrides </strong> <strong>Overrides </strong>
<Tooltip title="Here you can specify which users should get this variant."> <Tooltip title="Here you can specify which users should get this variant.">
<Info <Info
style={{ style={{
width: '18.5px', width: '18.5px',
height: '18.5px', height: '18.5px',
color: 'grey',
}} }}
/> />
</Tooltip> </Tooltip>
@ -301,7 +311,13 @@ const AddVariant = ({
updateOverrideValues={updateOverrideValues} updateOverrideValues={updateOverrideValues}
updateValues={updateOverrideValues} updateValues={updateOverrideValues}
/> />
<Button onClick={onAddOverride}>Add override</Button>{' '} <Button
onClick={onAddOverride}
variant="contained"
color="primary"
>
Add override
</Button>{' '}
</form> </form>
</Dialog> </Dialog>
); );

View File

@ -41,7 +41,13 @@ const OverrideConfig = ({
return ( return (
<Grid container key={`override=${i}`} alignItems="center"> <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 <MySelect
name="contextName" name="contextName"
label="Context Field" label="Context Field"
@ -53,7 +59,7 @@ const OverrideConfig = ({
onChange={updateOverrideType(i)} onChange={updateOverrideType(i)}
/> />
</Grid> </Grid>
<Grid md={7} item> <Grid md={7} sm={7} xs={6} item>
<ConditionallyRender <ConditionallyRender
condition={legalValues && legalValues.length > 0} condition={legalValues && legalValues.length > 0}
show={ show={
@ -68,6 +74,7 @@ const OverrideConfig = ({
getOptionLabel={option => option} getOptionLabel={option => option}
defaultValue={o.values} defaultValue={o.values}
value={o.values} value={o.values}
style={{ width: '100%' }}
filterSelectedOptions filterSelectedOptions
size="small" size="small"
renderInput={params => ( renderInput={params => (
@ -75,6 +82,7 @@ const OverrideConfig = ({
{...params} {...params}
variant="outlined" variant="outlined"
label="Legal values" label="Legal values"
style={{ width: '100%' }}
/> />
)} )}
/> />

View File

@ -16,255 +16,253 @@ export const Footer = () => {
<Grid item md={4} xs={12}> <Grid item md={4} xs={12}>
<ShowApiDetailsContainer /> <ShowApiDetailsContainer />
</Grid> </Grid>
<Grid item xs="12" md="auto"> <Grid item xs={12} md="auto">
<Grid container spacing={7} direction="row" > <Grid container spacing={7} direction="row">
<Grid item> <Grid item>
<section title="Unleash SDK"> <section title="Unleash SDK">
<h4>Server SDKs</h4> <h4>Server SDKs</h4>
<List className={styles.list} dense> <List className={styles.list} dense>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/node_sdk" href="https://docs.getunleash.io/sdks/node_sdk"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
Node.js Node.js
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/java_sdk" href="https://docs.getunleash.io/sdks/java_sdk"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
Java Java
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/go_sdk" href="https://docs.getunleash.io/sdks/go_sdk"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
Go Go
</a> </a>
} }
/> />
</ListItem>{' '} </ListItem>{' '}
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/ruby_sdk" href="https://docs.getunleash.io/sdks/ruby_sdk"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
Ruby Ruby
</a> </a>
} }
/> />
</ListItem>{' '} </ListItem>{' '}
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/python_sdk" href="https://docs.getunleash.io/sdks/python_sdk"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
Python Python
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/dot_net_sdk" href="https://docs.getunleash.io/sdks/dot_net_sdk"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
.NET .NET
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/php_sdk" href="https://docs.getunleash.io/sdks/php_sdk"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
PHP PHP
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks" href="https://docs.getunleash.io/sdks"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
All SDKs All SDKs
</a> </a>
} }
/> />
</ListItem> </ListItem>
</List> </List>
</section> </section>
</Grid> </Grid>
<Grid item justifyContent="center"> <Grid item>
<section title="Unleash SDK"> <section title="Unleash SDK">
<h4>Frontend SDKs</h4> <h4>Frontend SDKs</h4>
<List className={styles.list} dense> <List className={styles.list} dense>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/unleash-proxy" href="https://docs.getunleash.io/sdks/unleash-proxy"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
Unleash Proxy Unleash Proxy
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/proxy-javascript" href="https://docs.getunleash.io/sdks/proxy-javascript"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
JavaScript SDK JavaScript SDK
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/proxy-react" href="https://docs.getunleash.io/sdks/proxy-react"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
React SDK React SDK
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/proxy-ios" href="https://docs.getunleash.io/sdks/proxy-ios"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
iOS SDK iOS SDK
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://docs.getunleash.io/sdks/android_proxy_sdk" href="https://docs.getunleash.io/sdks/android_proxy_sdk"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
Android SDK Android SDK
</a> </a>
} }
/> />
</ListItem> </ListItem>
</List> </List>
</section> </section>
</Grid> </Grid>
<Grid item> <Grid item>
<section> <section>
<h4>About</h4> <h4>About</h4>
<List className={styles.list} dense> <List className={styles.list} dense>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://www.getunleash.io/" href="https://www.getunleash.io/"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
getunleash.io getunleash.io
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://twitter.com/getunleash" href="https://twitter.com/getunleash"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
Twitter Twitter
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://www.linkedin.com/company/getunleash" href="https://www.linkedin.com/company/getunleash"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
LinkedIn LinkedIn
</a> </a>
} }
/> />
</ListItem> </ListItem>
<ListItem className={styles.listItem}> <ListItem className={styles.listItem}>
<ListItemText <ListItemText
primary={ primary={
<a <a
href="https://github.com/Unleash/unleash" href="https://github.com/Unleash/unleash"
className={styles.link} className={styles.link}
target="_blank" target="_blank"
> >
GitHub GitHub
</a> </a>
} }
/> />
</ListItem> </ListItem>
</List> </List>
</section> </section>
</Grid>
</Grid>
</Grid> </Grid>
</Grid> </Grid>
</Grid>
</Grid>
</footer> </footer>
); );
}; };

View File

@ -199,7 +199,6 @@ exports[`should render DrawerMenu 1`] = `
</div> </div>
<div <div
className="MuiGrid-root MuiGrid-item" className="MuiGrid-root MuiGrid-item"
justifyContent="center"
> >
<section <section
title="Unleash SDK" title="Unleash SDK"
@ -602,7 +601,6 @@ exports[`should render DrawerMenu with "features" selected 1`] = `
</div> </div>
<div <div
className="MuiGrid-root MuiGrid-item" className="MuiGrid-root MuiGrid-item"
justifyContent="center"
> >
<section <section
title="Unleash SDK" title="Unleash SDK"