mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
add info box in project page + make api ui responsive
This commit is contained in:
parent
ddf7715d01
commit
02c17571de
@ -12,16 +12,33 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
maxWidth: '400px',
|
maxWidth: '400px',
|
||||||
marginBottom: '1rem',
|
marginBottom: '1rem',
|
||||||
},
|
},
|
||||||
cardLink: {
|
|
||||||
color: 'inherit',
|
|
||||||
textDecoration: 'none',
|
|
||||||
border: 'none',
|
|
||||||
padding: '0',
|
|
||||||
background: 'transparent',
|
|
||||||
fontFamily: theme.typography.fontFamily,
|
|
||||||
pointer: 'cursor',
|
|
||||||
},
|
|
||||||
center: {
|
center: {
|
||||||
textAlign: 'center'
|
textAlign: 'center'
|
||||||
|
},
|
||||||
|
actionsContainer: {
|
||||||
|
textAlign: 'center',
|
||||||
|
display: 'flex-inline',
|
||||||
|
flexWrap: 'nowrap'
|
||||||
|
},
|
||||||
|
hideSM:{
|
||||||
|
[theme.breakpoints.down('sm')]: {
|
||||||
|
display: 'none'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideMD:{
|
||||||
|
[theme.breakpoints.down('md')]: {
|
||||||
|
display: 'none'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideXS:{
|
||||||
|
[theme.breakpoints.down('xs')]: {
|
||||||
|
display: 'none'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
token:{
|
||||||
|
textAlign: 'left',
|
||||||
|
[theme.breakpoints.up('sm')]: {
|
||||||
|
display: 'none'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useContext, useState } from 'react';
|
import { useContext, useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Button, IconButton, Table, TableBody, TableCell, TableHead, TableRow } from '@material-ui/core';
|
import { Button, IconButton, Table, TableBody, TableCell, TableHead, TableRow, } from '@material-ui/core';
|
||||||
import AccessContext from '../../../contexts/AccessContext';
|
import AccessContext from '../../../contexts/AccessContext';
|
||||||
import useToast from '../../../hooks/useToast';
|
import useToast from '../../../hooks/useToast';
|
||||||
import useLoading from '../../../hooks/useLoading';
|
import useLoading from '../../../hooks/useLoading';
|
||||||
@ -15,7 +15,7 @@ import { CREATE_API_TOKEN, DELETE_API_TOKEN } from '../../AccessProvider/permiss
|
|||||||
import { useStyles } from './ApiTokenList.styles';
|
import { useStyles } from './ApiTokenList.styles';
|
||||||
import { formatDateWithLocale } from '../../common/util';
|
import { formatDateWithLocale } from '../../common/util';
|
||||||
import Secret from './secret';
|
import Secret from './secret';
|
||||||
import { Delete } from '@material-ui/icons';
|
import { Delete, FileCopy } from '@material-ui/icons';
|
||||||
import ApiTokenCreate from '../ApiTokenCreate/ApiTokenCreate';
|
import ApiTokenCreate from '../ApiTokenCreate/ApiTokenCreate';
|
||||||
import Dialogue from '../../common/Dialogue';
|
import Dialogue from '../../common/Dialogue';
|
||||||
|
|
||||||
@ -73,6 +73,14 @@ const ApiTokenList = ({ location }: IApiTokenList) => {
|
|||||||
text: 'Successfully created API token.',
|
text: 'Successfully created API token.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const copyToken = (value: string) => {
|
||||||
|
navigator.clipboard.writeText(value);
|
||||||
|
setToastData({
|
||||||
|
type: 'success',
|
||||||
|
show: true,
|
||||||
|
text: `Token is copied to clipboard`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const onDeleteToken = async () => {
|
const onDeleteToken = async () => {
|
||||||
if(delToken) {
|
if(delToken) {
|
||||||
@ -101,65 +109,81 @@ const ApiTokenList = ({ location }: IApiTokenList) => {
|
|||||||
<Table size="small">
|
<Table size="small">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>Created</TableCell>
|
<TableCell className={styles.hideSM}>Created</TableCell>
|
||||||
<TableCell>Username</TableCell>
|
<TableCell className={styles.hideSM}>hideSM</TableCell>
|
||||||
<TableCell className={styles.center}>Type</TableCell>
|
<TableCell className={`${styles.center} ${styles.hideXS}`}>Type</TableCell>
|
||||||
<ConditionallyRender condition={uiConfig.flags.E} show={<>
|
<ConditionallyRender condition={uiConfig.flags.E} show={<>
|
||||||
<TableCell className={styles.center}>Project</TableCell>
|
<TableCell className={`${styles.center} ${styles.hideXS}`}>Project</TableCell>
|
||||||
<TableCell className={styles.center}>Environment</TableCell>
|
<TableCell className={`${styles.center} ${styles.hideXS}`}>Environment</TableCell>
|
||||||
</>} />
|
</>} />
|
||||||
<TableCell>Secret</TableCell>
|
<TableCell className={styles.hideMD}>Secret</TableCell>
|
||||||
<TableCell align="right">Action</TableCell>
|
<TableCell className={styles.token}>Token</TableCell>
|
||||||
|
<TableCell className={styles.actionsContainer}>Actions</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{tokens.map(item => {
|
{tokens.map(item => {
|
||||||
return (
|
return (
|
||||||
<TableRow key={item.secret}>
|
<TableRow key={item.secret}>
|
||||||
<TableCell align="left">
|
<TableCell align="left" className={styles.hideSM}>
|
||||||
{formatDateWithLocale(
|
{formatDateWithLocale(
|
||||||
item.createdAt,
|
item.createdAt,
|
||||||
location.locale
|
location.locale
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="left">
|
<TableCell align="left" className={styles.hideSM}>
|
||||||
{item.username}
|
{item.username}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={styles.center}>
|
<TableCell className={`${styles.center} ${styles.hideXS}`}>
|
||||||
{item.type}
|
{item.type}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<ConditionallyRender condition={uiConfig.flags.E} show={<>
|
<ConditionallyRender condition={uiConfig.flags.E} show={<>
|
||||||
<TableCell className={styles.center}>
|
<TableCell className={`${styles.center} ${styles.hideXS}`}>
|
||||||
{renderProject(item.project)}
|
{renderProject(item.project)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={styles.center}>
|
<TableCell className={`${styles.center} ${styles.hideXS}`}>
|
||||||
{item.environment}
|
{item.environment}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
<TableCell className={styles.token}>
|
||||||
|
<b>Type:</b> {item.type}<br/>
|
||||||
|
<b>Env:</b> {item.environment}<br/>
|
||||||
|
<b>Project:</b> {renderProject(item.project)}
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
</>} />
|
</>} />
|
||||||
|
|
||||||
<TableCell>
|
<TableCell className={styles.hideMD}>
|
||||||
<Secret value={item.secret} />
|
<Secret value={item.secret} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<ConditionallyRender
|
<TableCell
|
||||||
condition={hasAccess(DELETE_API_TOKEN)}
|
className={styles.actionsContainer}
|
||||||
show={<TableCell
|
>
|
||||||
width="20"
|
<IconButton
|
||||||
style={{ textAlign: 'right' }}
|
onClick={() => {
|
||||||
>
|
copyToken(item.secret)
|
||||||
<IconButton
|
} }
|
||||||
onClick={() => {
|
|
||||||
setDeleteToken(item);
|
|
||||||
setShowDelete(true);
|
|
||||||
} }
|
|
||||||
>
|
>
|
||||||
<Delete />
|
<FileCopy />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</TableCell>} />
|
<ConditionallyRender
|
||||||
|
condition={hasAccess(DELETE_API_TOKEN)}
|
||||||
|
show={
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
setDeleteToken(item);
|
||||||
|
setShowDelete(true);
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
<Delete />
|
||||||
|
</IconButton>
|
||||||
|
} />
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>)
|
</Table>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,29 +1,9 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { IconButton } from '@material-ui/core';
|
|
||||||
import { Visibility } from '@material-ui/icons';
|
|
||||||
function Secret({ value }) {
|
function Secret({ value }) {
|
||||||
const [show, setShow] = useState(false);
|
|
||||||
const toggle = evt => {
|
|
||||||
evt.preventDefault();
|
|
||||||
setShow(!show);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{show ? (
|
<span style={{ width: '250px', display: 'inline-block' }}>************************************</span>
|
||||||
<input readOnly value={value} style={{ width: '250px' }} />
|
|
||||||
) : (
|
|
||||||
<span style={{ width: '250px', display: 'inline-block' }}>************************************</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<IconButton
|
|
||||||
aria-label="Show token"
|
|
||||||
onClick={toggle}
|
|
||||||
title="Show token"
|
|
||||||
>
|
|
||||||
<Visibility style={{ marginLeft: '5px', fontSize: '1.2em' }} />
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,9 @@ import useProject from '../../../hooks/api/getters/useProject/useProject';
|
|||||||
import { FormControlLabel, FormGroup, Switch } from '@material-ui/core';
|
import { FormControlLabel, FormGroup, Switch } from '@material-ui/core';
|
||||||
import useProjectApi from '../../../hooks/api/actions/useProjectApi/useProjectApi';
|
import useProjectApi from '../../../hooks/api/actions/useProjectApi/useProjectApi';
|
||||||
import EnvironmentDisableConfirm from './EnvironmentDisableConfirm/EnvironmentDisableConfirm';
|
import EnvironmentDisableConfirm from './EnvironmentDisableConfirm/EnvironmentDisableConfirm';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { Alert } from '@material-ui/lab';
|
||||||
|
|
||||||
|
|
||||||
export interface ProjectEnvironment {
|
export interface ProjectEnvironment {
|
||||||
name: string;
|
name: string;
|
||||||
@ -42,6 +45,7 @@ const ProjectEnvironmentList = ({projectId}: ProjectEnvironmentListProps) => {
|
|||||||
const ref = useLoading(loading);
|
const ref = useLoading(loading);
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
|
||||||
|
|
||||||
const refetch = () => {
|
const refetch = () => {
|
||||||
refetchEnvs();
|
refetchEnvs();
|
||||||
refetchProject();
|
refetchProject();
|
||||||
@ -132,9 +136,26 @@ const ProjectEnvironmentList = ({projectId}: ProjectEnvironmentListProps) => {
|
|||||||
headerContent={
|
headerContent={
|
||||||
<HeaderTitle
|
<HeaderTitle
|
||||||
title={`Configure environments for "${project?.name}"`}
|
title={`Configure environments for "${project?.name}"`}
|
||||||
/>
|
/>}
|
||||||
}
|
|
||||||
>
|
>
|
||||||
|
<Alert severity="info">
|
||||||
|
<b>Important!</b> In order for your application to ONLY retrieve feature toggle activation strategies for a specific environment, the application<br/> must use an environment-specific API key. You can look up the environment-specific API keys {' '}
|
||||||
|
<Link
|
||||||
|
to='/admin/api'
|
||||||
|
>
|
||||||
|
here.
|
||||||
|
</Link>{' '}
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
Your administrator can configure an environment-specific API key and add it to your SDK if you can't find it on the list.
|
||||||
|
If you are an administrator you can create a new API key {' '}
|
||||||
|
<Link
|
||||||
|
to='/admin/api'
|
||||||
|
>
|
||||||
|
here.
|
||||||
|
</Link>{' '}
|
||||||
|
</Alert>
|
||||||
|
<br/>
|
||||||
<ConditionallyRender condition={error} show={renderError()} />
|
<ConditionallyRender condition={error} show={renderError()} />
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
|
Loading…
Reference in New Issue
Block a user