mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
refactor: port ApiDetails to useSWR and TS (#653)
* refactor: add missing react-test-renderer types * refactor: make IVersionInfo match backend type * refactor: allow falsy conditions in ConditionallyRender * refactor: port ApiDetails to useSWR and TS * refactor: use arrow functions * refactor: move useUiConfig to Footer * refactor: add component name to props type * refactor: move ApiDetails helpers to own file * refactor: combine ApiDetails helper components * refactor: move ApiDetails to the Footer dir * Revert "refactor: allow falsy conditions in ConditionallyRender" This reverts commit 70d75951eb4d0611e80b015a97243404618493ed. * refactor: use booleans for ConditionallyRender * refactor: use a subdir for ApiDetails * refactor: fix ApiDetails helpers filename * refactor: reformat using correct prettier settings
This commit is contained in:
parent
23c6c0cd8f
commit
74733e5b44
@ -52,6 +52,7 @@
|
||||
"@types/react": "17.0.38",
|
||||
"@types/react-dom": "17.0.11",
|
||||
"@types/react-router-dom": "5.3.3",
|
||||
"@types/react-test-renderer": "^17.0.1",
|
||||
"@types/react-timeago": "4.1.3",
|
||||
"@welldone-software/why-did-you-render": "6.2.3",
|
||||
"array-move": "3.0.1",
|
||||
|
@ -1,38 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import ShowApiDetailsComponent from '../show-api-details-component';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
test('renders correctly with empty version', () => {
|
||||
const uiConfig = {
|
||||
name: 'Unleash',
|
||||
slogan: 'We are the best!',
|
||||
environment: 'test',
|
||||
version: '',
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ShowApiDetailsComponent uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders correctly with ui-config', () => {
|
||||
const uiConfig = {
|
||||
name: 'Unleash',
|
||||
slogan: 'We are the best!',
|
||||
environment: 'test',
|
||||
version: '1.1.0',
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ShowApiDetailsComponent uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders correctly without uiConfig', () => {
|
||||
const uiConfig = {
|
||||
name: 'Unleash',
|
||||
version: '1.1.0',
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ShowApiDetailsComponent uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
@ -1,45 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ConditionallyRender from '../common/ConditionallyRender/ConditionallyRender';
|
||||
|
||||
class ShowApiDetailsComponent extends Component {
|
||||
static propTypes = {
|
||||
uiConfig: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { slogan, environment, version, versionInfo, name } = this.props.uiConfig;
|
||||
let versionStr;
|
||||
let updateNotification;
|
||||
let instanceId;
|
||||
if (versionInfo) {
|
||||
if (versionInfo.current.enterprise) {
|
||||
versionStr = `${name} ${versionInfo.current.enterprise}`;
|
||||
if (Object.keys(versionInfo.latest).includes('enterprise') && !versionInfo.isLatest) {
|
||||
updateNotification = `Upgrade available - Latest Enterprise release: ${versionInfo.latest.enterprise}`;
|
||||
}
|
||||
} else {
|
||||
versionStr = `${name} ${versionInfo.current.oss}`;
|
||||
if (Object.keys(versionInfo.latest).includes('oss') && !versionInfo.isLatest) {
|
||||
updateNotification = `Upgrade available - Latest OSS release: ${versionInfo.latest.oss}`;
|
||||
}
|
||||
}
|
||||
instanceId = versionInfo.instanceId;
|
||||
} else {
|
||||
versionStr = `${name} ${version}`;
|
||||
}
|
||||
return (
|
||||
<section title="API details">
|
||||
<h4>{`${versionStr}`} <ConditionallyRender condition={environment} show={<small>({environment})</small>} /></h4>
|
||||
|
||||
<ConditionallyRender condition={updateNotification} show={<small>{updateNotification}<br /></small>} />
|
||||
<br />
|
||||
<small>{slogan}</small>
|
||||
<br />
|
||||
<ConditionallyRender condition={instanceId} show={<small>{`${instanceId}`}</small>} />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ShowApiDetailsComponent;
|
@ -1,10 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import ShowApiDetailsComponent from './show-api-details-component';
|
||||
|
||||
const mapDispatchToProps = {};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
uiConfig: state.uiConfig.toJS(),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ShowApiDetailsComponent);
|
46
frontend/src/component/menu/Footer/ApiDetails/ApiDetails.tsx
Normal file
46
frontend/src/component/menu/Footer/ApiDetails/ApiDetails.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { ReactElement } from 'react';
|
||||
import ConditionallyRender from '../../../common/ConditionallyRender';
|
||||
import {
|
||||
formatCurrentVersion,
|
||||
formatUpdateNotification,
|
||||
IPartialUiConfig,
|
||||
} from './apidetails.helpers';
|
||||
|
||||
interface IApiDetailsProps {
|
||||
uiConfig: IPartialUiConfig;
|
||||
}
|
||||
|
||||
export const ApiDetails = (props: IApiDetailsProps): ReactElement => {
|
||||
const instanceId = props.uiConfig.versionInfo?.instanceId;
|
||||
const currentVersion = formatCurrentVersion(props.uiConfig);
|
||||
const environment = props.uiConfig.environment;
|
||||
const updateNotification = formatUpdateNotification(props.uiConfig);
|
||||
|
||||
return (
|
||||
<section title="API details">
|
||||
<h4>
|
||||
{currentVersion}{' '}
|
||||
<ConditionallyRender
|
||||
condition={Boolean(environment)}
|
||||
show={<small>({environment})</small>}
|
||||
/>
|
||||
</h4>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(updateNotification)}
|
||||
show={
|
||||
<small>
|
||||
{updateNotification}
|
||||
<br />
|
||||
</small>
|
||||
}
|
||||
/>
|
||||
<br />
|
||||
<small>{props.uiConfig.slogan}</small>
|
||||
<br />
|
||||
<ConditionallyRender
|
||||
condition={Boolean(instanceId)}
|
||||
show={<small>{`${instanceId}`}</small>}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
};
|
@ -0,0 +1,38 @@
|
||||
import { IVersionInfo } from '../../../../interfaces/uiConfig';
|
||||
|
||||
export interface IPartialUiConfig {
|
||||
name: string;
|
||||
version: string;
|
||||
slogan?: string;
|
||||
environment?: string;
|
||||
versionInfo?: IVersionInfo;
|
||||
}
|
||||
|
||||
export const formatCurrentVersion = (uiConfig: IPartialUiConfig): string => {
|
||||
const current = uiConfig.versionInfo?.current;
|
||||
|
||||
if (current?.enterprise) {
|
||||
return `${uiConfig.name} ${current.enterprise}`;
|
||||
}
|
||||
|
||||
if (current?.oss) {
|
||||
return `${uiConfig.name} ${current.oss}`;
|
||||
}
|
||||
|
||||
return `${uiConfig.name} ${uiConfig.version}`;
|
||||
};
|
||||
|
||||
export const formatUpdateNotification = (
|
||||
uiConfig: IPartialUiConfig
|
||||
): string | undefined => {
|
||||
const latest = uiConfig.versionInfo?.latest;
|
||||
const isLatest = uiConfig.versionInfo?.isLatest;
|
||||
|
||||
if (latest?.enterprise && !isLatest) {
|
||||
return `Upgrade available - Latest Enterprise release: ${latest.enterprise}`;
|
||||
}
|
||||
|
||||
if (latest?.oss && !isLatest) {
|
||||
return `Upgrade available - Latest OSS release: ${latest.oss}`;
|
||||
}
|
||||
};
|
@ -1,19 +1,19 @@
|
||||
/* eslint-disable react/jsx-no-target-blank */
|
||||
|
||||
import { List, ListItem, ListItemText, Grid } from '@material-ui/core';
|
||||
|
||||
import ShowApiDetailsContainer from '../../api/show-api-details-container';
|
||||
|
||||
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { ApiDetails } from './ApiDetails/ApiDetails';
|
||||
import { useStyles } from './Footer.styles';
|
||||
|
||||
export const Footer = () => {
|
||||
const styles = useStyles();
|
||||
const { uiConfig } = useUiConfig();
|
||||
|
||||
return (
|
||||
<footer className={styles.footer}>
|
||||
<Grid container justifyContent="center" spacing={10} style={{marginBottom: 0}}>
|
||||
<Grid item md={4} xs={12}>
|
||||
<ShowApiDetailsContainer />
|
||||
<ApiDetails uiConfig={uiConfig} />
|
||||
</Grid>
|
||||
<Grid item xs={12} md="auto">
|
||||
<Grid container spacing={7} direction="row">
|
||||
|
@ -42,6 +42,27 @@ exports[`renders correctly with ui-config 1`] = `
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`renders correctly with versionInfo 1`] = `
|
||||
<section
|
||||
title="API details"
|
||||
>
|
||||
<h4>
|
||||
Unleash 1.2.3
|
||||
|
||||
</h4>
|
||||
<small>
|
||||
Upgrade available - Latest Enterprise release: 1.2.4
|
||||
<br />
|
||||
</small>
|
||||
<br />
|
||||
<small />
|
||||
<br />
|
||||
<small>
|
||||
1
|
||||
</small>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`renders correctly without uiConfig 1`] = `
|
||||
<section
|
||||
title="API details"
|
@ -19,11 +19,13 @@ exports[`should render DrawerMenu 1`] = `
|
||||
title="API details"
|
||||
>
|
||||
<h4>
|
||||
undefined undefined
|
||||
Unleash 3.x
|
||||
|
||||
</h4>
|
||||
<br />
|
||||
<small />
|
||||
<small>
|
||||
The enterprise ready feature toggle service.
|
||||
</small>
|
||||
<br />
|
||||
</section>
|
||||
</div>
|
||||
@ -445,11 +447,13 @@ exports[`should render DrawerMenu with "features" selected 1`] = `
|
||||
title="API details"
|
||||
>
|
||||
<h4>
|
||||
undefined undefined
|
||||
Unleash 3.x
|
||||
|
||||
</h4>
|
||||
<br />
|
||||
<small />
|
||||
<small>
|
||||
The enterprise ready feature toggle service.
|
||||
</small>
|
||||
<br />
|
||||
</section>
|
||||
</div>
|
||||
|
53
frontend/src/component/menu/__tests__/apidetails.test.tsx
Normal file
53
frontend/src/component/menu/__tests__/apidetails.test.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { ApiDetails } from '../Footer/ApiDetails/ApiDetails';
|
||||
|
||||
test('renders correctly with empty version', () => {
|
||||
const uiConfig = {
|
||||
name: 'Unleash',
|
||||
slogan: 'We are the best!',
|
||||
environment: 'test',
|
||||
version: '',
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ApiDetails uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders correctly with ui-config', () => {
|
||||
const uiConfig = {
|
||||
name: 'Unleash',
|
||||
slogan: 'We are the best!',
|
||||
environment: 'test',
|
||||
version: '1.1.0',
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ApiDetails uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders correctly without uiConfig', () => {
|
||||
const uiConfig = {
|
||||
name: 'Unleash',
|
||||
version: '1.1.0',
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ApiDetails uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('renders correctly with versionInfo', () => {
|
||||
const uiConfig = {
|
||||
name: 'Unleash',
|
||||
version: '1.2.3',
|
||||
versionInfo: {
|
||||
instanceId: '1',
|
||||
isLatest: false,
|
||||
current: { enterprise: '1.2.3', oss: '1.2.3' },
|
||||
latest: { enterprise: '1.2.4', oss: '1.2.4' },
|
||||
},
|
||||
};
|
||||
|
||||
const tree = renderer.create(<ApiDetails uiConfig={uiConfig} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
@ -2,33 +2,17 @@ import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { ThemeProvider } from '@material-ui/core';
|
||||
import { Provider } from 'react-redux';
|
||||
import { createStore } from 'redux';
|
||||
|
||||
import Footer from '../Footer/Footer';
|
||||
import theme from '../../../themes/main-theme';
|
||||
|
||||
const mockStore = {
|
||||
uiConfig: {
|
||||
toJS: () => ({
|
||||
flags: {
|
||||
P: true,
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
const mockReducer = state => state;
|
||||
|
||||
test('should render DrawerMenu', () => {
|
||||
const tree = renderer.create(
|
||||
<Provider store={createStore(mockReducer, mockStore)}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<MemoryRouter>
|
||||
<Footer />
|
||||
</MemoryRouter>
|
||||
</ThemeProvider>
|
||||
</Provider>
|
||||
<ThemeProvider theme={theme}>
|
||||
<MemoryRouter>
|
||||
<Footer />
|
||||
</MemoryRouter>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
@ -36,13 +20,11 @@ test('should render DrawerMenu', () => {
|
||||
|
||||
test('should render DrawerMenu with "features" selected', () => {
|
||||
const tree = renderer.create(
|
||||
<Provider store={createStore(mockReducer, mockStore)}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<MemoryRouter initialEntries={['/features']}>
|
||||
<Footer />
|
||||
</MemoryRouter>
|
||||
</ThemeProvider>
|
||||
</Provider>
|
||||
<ThemeProvider theme={theme}>
|
||||
<MemoryRouter initialEntries={['/features']}>
|
||||
<Footer />
|
||||
</MemoryRouter>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
|
@ -19,11 +19,11 @@ export interface IFlags {
|
||||
export interface IVersionInfo {
|
||||
instanceId: string;
|
||||
isLatest: boolean;
|
||||
latest: Object;
|
||||
current: ICurrent;
|
||||
latest: Partial<IVersion>;
|
||||
current: IVersion;
|
||||
}
|
||||
|
||||
export interface ICurrent {
|
||||
export interface IVersion {
|
||||
oss: string;
|
||||
enterprise: string;
|
||||
}
|
||||
|
@ -2186,6 +2186,13 @@
|
||||
"@types/history" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-test-renderer@^17.0.1":
|
||||
version "17.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz#3120f7d1c157fba9df0118dae20cb0297ee0e06b"
|
||||
integrity sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-timeago@4.1.3":
|
||||
version "4.1.3"
|
||||
resolved "https://registry.npmjs.org/@types/react-timeago/-/react-timeago-4.1.3.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user