diff --git a/packages/core/src/components/CircleProgress.js b/packages/core/src/components/CircleProgress.js deleted file mode 100644 index f11f9d193b..0000000000 --- a/packages/core/src/components/CircleProgress.js +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { withStyles } from '@material-ui/core'; -import { Circle } from 'rc-progress'; -import { COLORS, V1 } from '../theme/BackstageTheme'; - -const styles = theme => ({ - root: { - position: 'relative', - lineHeight: 0, - }, - overlay: { - position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -60%)', - fontSize: 45, - fontWeight: 'bold', - color: theme.palette.textSubtle, - }, - circle: { - width: '80%', - transform: 'translate(10%, 0)', - }, -}); - -class CircleProgress extends Component { - static propTypes = { - value: PropTypes.any.isRequired, - fractional: PropTypes.bool, - classes: PropTypes.object.isRequired, - inverse: PropTypes.bool, - unit: PropTypes.string, - max: PropTypes.number, - }; - - static defaultProps = { - fractional: true, - inverse: false, - unit: '%', - max: 100, - }; - - static getProgressColor(value, inverse, max /* , classes */) { - if (isNaN(value)) { - return V1.palette.textVerySubtle; - } - - const actualMax = max ? max : CircleProgress.defaultProps.max; - const actualValue = inverse ? actualMax - value : value; - - if (actualValue < actualMax / 3) { - return COLORS.STATUS.ERROR; - } else if (actualValue < actualMax * (2 / 3)) { - return COLORS.STATUS.WARNING; - } - return COLORS.STATUS.OK; - } - - render() { - const { value, fractional, classes, inverse, unit, max } = this.props; - - const asPercentage = fractional ? Math.round(value * max) : value; - const asActual = max !== 100 ? Math.round(value) : asPercentage; - - return ( -
- -
- {isNaN(value) ? 'N/A' : `${asActual}${unit}`} -
-
- ); - } -} - -export default withStyles(styles)(CircleProgress); diff --git a/packages/core/src/components/CircleProgress.test.js b/packages/core/src/components/CircleProgress.test.js index 9686a62c1c..7d4b294dc1 100644 --- a/packages/core/src/components/CircleProgress.test.js +++ b/packages/core/src/components/CircleProgress.test.js @@ -17,8 +17,8 @@ import React from 'react'; import { render } from '@testing-library/react'; import { wrapInThemedTestApp } from '../testUtils'; -import CircleProgress from './CircleProgress'; -import { COLORS, V1 } from '../theme/BackstageTheme'; +import CircleProgress, { getProgressColor } from './CircleProgress'; +import { COLORS } from '../theme/BackstageTheme'; describe('', () => { it('renders without exploding', () => { @@ -53,18 +53,16 @@ describe('', () => { }); it('colors the progress correctly', () => { - expect(CircleProgress.getProgressColor()).toBe(V1.palette.textVerySubtle); - expect(CircleProgress.getProgressColor(10)).toBe(COLORS.STATUS.ERROR); - expect(CircleProgress.getProgressColor(50)).toBe(COLORS.STATUS.WARNING); - expect(CircleProgress.getProgressColor(90)).toBe(COLORS.STATUS.OK); + expect(getProgressColor()).toBe('#ddd'); + expect(getProgressColor(10)).toBe(COLORS.STATUS.ERROR); + expect(getProgressColor(50)).toBe(COLORS.STATUS.WARNING); + expect(getProgressColor(90)).toBe(COLORS.STATUS.OK); }); it('colors the inverse progress correctly', () => { - expect(CircleProgress.getProgressColor()).toBe(V1.palette.textVerySubtle); - expect(CircleProgress.getProgressColor(10, true)).toBe(COLORS.STATUS.OK); - expect(CircleProgress.getProgressColor(50, true)).toBe( - COLORS.STATUS.WARNING, - ); - expect(CircleProgress.getProgressColor(90, true)).toBe(COLORS.STATUS.ERROR); + expect(getProgressColor()).toBe('#ddd'); + expect(getProgressColor(10, true)).toBe(COLORS.STATUS.OK); + expect(getProgressColor(50, true)).toBe(COLORS.STATUS.WARNING); + expect(getProgressColor(90, true)).toBe(COLORS.STATUS.ERROR); }); }); diff --git a/packages/core/src/components/CircleProgress.tsx b/packages/core/src/components/CircleProgress.tsx new file mode 100644 index 0000000000..6d30916c81 --- /dev/null +++ b/packages/core/src/components/CircleProgress.tsx @@ -0,0 +1,103 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { makeStyles } from '@material-ui/core'; +import { Circle } from 'rc-progress'; +import React, { FC } from 'react'; +import { COLORS } from '../theme/BackstageTheme'; +import { BackstageTheme } from '../theme/theme'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + root: { + position: 'relative', + lineHeight: 0, + }, + overlay: { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -60%)', + fontSize: 45, + fontWeight: 'bold', + color: theme.palette.textSubtle, + }, + circle: { + width: '80%', + transform: 'translate(10%, 0)', + }, + colorUnknown: {}, +})); + +type Props = { + value: number; + fractional?: boolean; + inverse?: boolean; + unit?: string; + max?: number; +}; + +const defaultProps = { + fractional: true, + inverse: false, + unit: '%', + max: 100, +}; + +export function getProgressColor(value, inverse, max) { + if (isNaN(value)) { + return '#ddd'; + } + + const actualMax = max ? max : defaultProps.max; + const actualValue = inverse ? actualMax - value : value; + + if (actualValue < actualMax / 3) { + return COLORS.STATUS.ERROR; + } else if (actualValue < actualMax * (2 / 3)) { + return COLORS.STATUS.WARNING; + } + + return COLORS.STATUS.OK; +} + +const CircleProgress: FC = props => { + const classes = useStyles(props); + const { value, fractional, inverse, unit, max } = { + ...defaultProps, + ...props, + }; + + const asPercentage = fractional ? Math.round(value * max) : value; + const asActual = max !== 100 ? Math.round(value) : asPercentage; + + return ( +
+ +
+ {isNaN(value) ? 'N/A' : `${asActual}${unit}`} +
+
+ ); +}; + +export default CircleProgress; diff --git a/packages/core/src/components/ProgressCard.js b/packages/core/src/components/ProgressCard.js deleted file mode 100644 index d83019bcf0..0000000000 --- a/packages/core/src/components/ProgressCard.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { withStyles } from '@material-ui/core'; - -import InfoCard from '../layout/InfoCard'; -import CircleProgress from './CircleProgress'; - -const styles = { - root: { - height: '100%', - width: 250, - }, -}; - -class ProgressCard extends Component { - static propTypes = { - classes: PropTypes.object.isRequired, - title: PropTypes.string.isRequired, - subheader: PropTypes.string, - progress: PropTypes.oneOfType([PropTypes.number, PropTypes.string]) - .isRequired, - deepLink: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.shape({ - title: PropTypes.string.isRequired, - link: PropTypes.string.isRequired, - }), - ]), - gacontext: PropTypes.string, - }; - - render() { - const { - title, - subheader, - progress, - deepLink, - classes, - variant, - } = this.props; - const link = - deepLink && - (typeof deepLink === 'string' - ? { title: 'View more', link: deepLink } - : deepLink); - return ( -
- - - -
- ); - } -} - -export default withStyles(styles)(ProgressCard); diff --git a/packages/core/src/components/ProgressCard.tsx b/packages/core/src/components/ProgressCard.tsx new file mode 100644 index 0000000000..6a3b87ba89 --- /dev/null +++ b/packages/core/src/components/ProgressCard.tsx @@ -0,0 +1,67 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { FC } from 'react'; +import { makeStyles } from '@material-ui/core'; + +import InfoCard from '../layout/InfoCard'; +import CircleProgress from './CircleProgress'; + +type Props = { + title: string; + subheader?: string; + variant?: string; + progress: number | string; + deepLink?: string | { title: string; link: string }; + gacontext?: string; +}; + +const useStyles = makeStyles({ + root: { + height: '100%', + width: 250, + }, +}); + +const ProgressCard: FC = props => { + const classes = useStyles(props); + const { title, subheader, progress, deepLink, variant } = props; + + // TODO(freben): Make type more strict when InfoCard is written in TS + let link: any = undefined; + if (deepLink) { + if (typeof deepLink === 'string') { + link = { title: 'View more', link: deepLink }; + } else { + link = deepLink; + } + } + + return ( +
+ + + +
+ ); +}; + +export default ProgressCard; diff --git a/packages/core/src/theme/theme.d.ts b/packages/core/src/theme/theme.d.ts index 1e3a57dee3..db4dfe5e86 100644 --- a/packages/core/src/theme/theme.d.ts +++ b/packages/core/src/theme/theme.d.ts @@ -26,5 +26,18 @@ export type BackstageTheme = Theme & { running: string; background: string; }; + border: string; + textVerySubtle: string; + textSubtle: string; + highlight: string; + errorBackground: string; + warningBackground: string; + infoBackground: string; + errorText: string; + infoText: string; + warningText: string; + linkHover: string; + link: string; + gold: string; }; };