Merge branch 'master' into feature/techdocs-e2e

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-09-28 11:12:31 +02:00
1927 changed files with 64963 additions and 24801 deletions
@@ -18,7 +18,7 @@ import React from 'react';
import { Button, Typography } from '@material-ui/core';
import { CodeSnippet, EmptyState } from '@backstage/core-components';
const EXAMPLE = `import { createPlugin } from '@backstage/core';
const EXAMPLE = `import { createPlugin } from '@backstage/core-plugin-api';
export default createPlugin({
id: 'plugin-name',
@@ -17,8 +17,8 @@
import React from 'react';
import {
ListItem,
ListItemSecondaryAction,
ListItemText,
ListItemIcon,
Switch,
Tooltip,
} from '@material-ui/core';
@@ -31,20 +31,15 @@ type Props = {
};
export const FlagItem = ({ flag, enabled, toggleHandler }: Props) => (
<ListItem>
<ListItem divider button onClick={() => toggleHandler(flag.name)}>
<ListItemIcon>
<Tooltip placement="top" arrow title={enabled ? 'Disable' : 'Enable'}>
<Switch color="primary" checked={enabled} name={flag.name} />
</Tooltip>
</ListItemIcon>
<ListItemText
primary={flag.name}
secondary={`Registered in ${flag.pluginId} plugin`}
/>
<ListItemSecondaryAction>
<Tooltip placement="top" arrow title={enabled ? 'Disable' : 'Enable'}>
<Switch
color="primary"
checked={enabled}
onChange={() => toggleHandler(flag.name)}
name={flag.name}
/>
</Tooltip>
</ListItemSecondaryAction>
</ListItem>
);
@@ -15,7 +15,13 @@
*/
import React, { useCallback, useState } from 'react';
import { List } from '@material-ui/core';
import {
List,
TextField,
IconButton,
Grid,
Typography,
} from '@material-ui/core';
import { EmptyFlags } from './EmptyFlags';
import { FlagItem } from './FeatureFlagsItem';
@@ -25,6 +31,7 @@ import {
useApi,
} from '@backstage/core-plugin-api';
import { InfoCard } from '@backstage/core-components';
import ClearIcon from '@material-ui/icons/Clear';
export const UserSettingsFeatureFlags = () => {
const featureFlagsApi = useApi(featureFlagsApiRef);
@@ -35,6 +42,8 @@ export const UserSettingsFeatureFlags = () => {
);
const [state, setState] = useState<Record<string, boolean>>(initialFlagState);
const [filterInput, setFilterInput] = useState<string>('');
const inputRef = React.useRef<HTMLElement>();
const toggleFlag = useCallback(
(flagName: string) => {
@@ -59,10 +68,60 @@ export const UserSettingsFeatureFlags = () => {
return <EmptyFlags />;
}
const clearFilterInput = () => {
setFilterInput('');
inputRef?.current?.focus();
};
let filteredFeatureFlags = Array.from(featureFlags);
const filterInputParts = filterInput
.split(/\s/)
.map(part => part.trim().toLowerCase());
filterInputParts.forEach(
part =>
(filteredFeatureFlags = filteredFeatureFlags.filter(featureFlag =>
featureFlag.name.toLowerCase().includes(part),
)),
);
const Header = () => (
<Grid container style={{ justifyContent: 'space-between' }}>
<Grid item xs={6} md={8}>
<Typography variant="h5">Feature Flags</Typography>
</Grid>
{featureFlags.length >= 10 && (
<Grid item xs={6} md={4}>
<TextField
label="Filter"
style={{ display: 'flex', justifyContent: 'flex-end' }}
inputRef={ref => ref && ref.focus()}
InputProps={{
...(filterInput.length && {
endAdornment: (
<IconButton
aria-label="Clear filter"
onClick={clearFilterInput}
edge="end"
>
<ClearIcon />
</IconButton>
),
}),
}}
onChange={e => setFilterInput(e.target.value)}
value={filterInput}
/>
</Grid>
)}
</Grid>
);
return (
<InfoCard title="Feature Flags">
<InfoCard title={<Header />}>
<List dense>
{featureFlags.map(featureFlag => {
{filteredFeatureFlags.map(featureFlag => {
const enabled = Boolean(state[featureFlag.name]);
return (
+6
View File
@@ -14,6 +14,12 @@
* limitations under the License.
*/
/**
* A Backstage plugin that provides a settings page
*
* @packageDocumentation
*/
export {
userSettingsPlugin,
userSettingsPlugin as plugin,