Handle empties

This commit is contained in:
Marcus Eide
2020-10-06 15:00:41 +02:00
parent ae0de36689
commit d03a7646f5
7 changed files with 217 additions and 94 deletions
@@ -16,14 +16,29 @@
import React from 'react';
import { List } from '@material-ui/core';
import { InfoCard } from '@backstage/core';
import { configApiRef, InfoCard, useApi } from '@backstage/core';
import { EmptyProviders } from './EmptyProviders';
import { DefaultProviderSettings } from './DefaultProviderSettings';
type Props = {
providers: React.ReactNode;
providerSettings?: JSX.Element;
};
export const AuthProviders = ({ providers }: Props) => (
<InfoCard>
<List dense>{providers}</List>
</InfoCard>
);
export const AuthProviders = ({ providerSettings }: Props) => {
const configApi = useApi(configApiRef);
const providersConfig = configApi.getOptionalConfig('auth.providers');
const configuredProviders = providersConfig?.keys() || [];
const providers = providerSettings ?? (
<DefaultProviderSettings configuredProviders={configuredProviders} />
);
if (!providerSettings && !configuredProviders?.length) {
return <EmptyProviders />;
}
return (
<InfoCard>
<List dense>{providers}</List>
</InfoCard>
);
};
@@ -14,74 +14,70 @@
* limitations under the License.
*/
import {
configApiRef,
githubAuthApiRef,
gitlabAuthApiRef,
googleAuthApiRef,
oauth2ApiRef,
oktaAuthApiRef,
microsoftAuthApiRef,
useApi,
} from '@backstage/core';
import Star from '@material-ui/icons/Star';
import React from 'react';
import { ProviderSettingsItem } from './ProviderSettingsItem';
export const DefaultProviderSettings = () => {
const configApi = useApi(configApiRef);
const providersConfig = configApi.getOptionalConfig('auth.providers');
const providers = providersConfig?.keys() ?? [];
return (
<>
{providers.includes('google') && (
<ProviderSettingsItem
title="Google"
description={googleAuthApiRef.description}
apiRef={googleAuthApiRef}
icon={Star}
/>
)}
{providers.includes('microsoft') && (
<ProviderSettingsItem
title="Microsoft"
description={microsoftAuthApiRef.description}
apiRef={microsoftAuthApiRef}
icon={Star}
/>
)}
{providers.includes('github') && (
<ProviderSettingsItem
title="Github"
description={githubAuthApiRef.description}
apiRef={githubAuthApiRef}
icon={Star}
/>
)}
{providers.includes('gitlab') && (
<ProviderSettingsItem
title="Gitlab"
description={gitlabAuthApiRef.description}
apiRef={gitlabAuthApiRef}
icon={Star}
/>
)}
{providers.includes('okta') && (
<ProviderSettingsItem
title="Okta"
description={oktaAuthApiRef.description}
apiRef={oktaAuthApiRef}
icon={Star}
/>
)}
{providers.includes('oauth2') && (
<ProviderSettingsItem
title="YourOrg"
description={oauth2ApiRef.description}
apiRef={oauth2ApiRef}
icon={Star}
/>
)}
</>
);
type Props = {
configuredProviders: string[];
};
export const DefaultProviderSettings = ({ configuredProviders }: Props) => (
<>
{configuredProviders.includes('google') && (
<ProviderSettingsItem
title="Google"
description={googleAuthApiRef.description}
apiRef={googleAuthApiRef}
icon={Star}
/>
)}
{configuredProviders.includes('microsoft') && (
<ProviderSettingsItem
title="Microsoft"
description={microsoftAuthApiRef.description}
apiRef={microsoftAuthApiRef}
icon={Star}
/>
)}
{configuredProviders.includes('github') && (
<ProviderSettingsItem
title="Github"
description={githubAuthApiRef.description}
apiRef={githubAuthApiRef}
icon={Star}
/>
)}
{configuredProviders.includes('gitlab') && (
<ProviderSettingsItem
title="Gitlab"
description={gitlabAuthApiRef.description}
apiRef={gitlabAuthApiRef}
icon={Star}
/>
)}
{configuredProviders.includes('okta') && (
<ProviderSettingsItem
title="Okta"
description={oktaAuthApiRef.description}
apiRef={oktaAuthApiRef}
icon={Star}
/>
)}
{configuredProviders.includes('oauth2') && (
<ProviderSettingsItem
title="YourOrg"
description={oauth2ApiRef.description}
apiRef={oauth2ApiRef}
icon={Star}
/>
)}
</>
);
@@ -0,0 +1,59 @@
/*
* 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 from 'react';
import { CodeSnippet, EmptyState } from '@backstage/core';
import { Button, Typography } from '@material-ui/core';
const EXAMPLE = `
import { createPlugin } from '@backstage/core';
export default createPlugin({
id: 'welcome',
register({ router, featureFlags }) {
featureFlags.register('enable-example-feature');
},
});
`;
export const EmptyProviders = () => (
<EmptyState
missing="content"
title="No Authentication Providers"
description=""
action={
<>
<Typography variant="body1">
An example how how to add a feature flags is highlighted below:
</Typography>
<CodeSnippet
text={EXAMPLE}
language="typescript"
showLineNumbers
highlightedNumbers={[7]}
customStyle={{ background: 'inherit', fontSize: '115%' }}
/>
<Button
variant="contained"
color="primary"
href="https://backstage.io/docs/api/utility-apis"
>
Read More
</Button>
</>
}
/>
);
@@ -0,0 +1,59 @@
/*
* 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 from 'react';
import { CodeSnippet, EmptyState } from '@backstage/core';
import { Button, Typography } from '@material-ui/core';
const EXAMPLE = `
import { createPlugin } from '@backstage/core';
export default createPlugin({
id: 'welcome',
register({ router, featureFlags }) {
featureFlags.register('enable-example-feature');
},
});
`;
export const EmptyFlags = () => (
<EmptyState
missing="content"
title="No Feature Flags"
description="Feature Flags makes it possible for plugins to register features in Backstage for users to opt into. You can use this to split out logic in your code for manual A/B testing, etc."
action={
<>
<Typography variant="body1">
An example how how to add a feature flags is highlighted below:
</Typography>
<CodeSnippet
text={EXAMPLE}
language="typescript"
showLineNumbers
highlightedNumbers={[7]}
customStyle={{ background: 'inherit', fontSize: '115%' }}
/>
<Button
variant="contained"
color="primary"
href="https://backstage.io/docs/api/utility-apis"
>
Read More
</Button>
</>
}
/>
);
@@ -14,25 +14,25 @@
* limitations under the License.
*/
import React, { useState, useCallback } from 'react';
import { List } from '@material-ui/core';
import React, { useCallback, useState } from 'react';
import {
useApi,
featureFlagsApiRef,
FeatureFlagName,
FeatureFlagState,
featureFlagsApiRef,
FeatureFlagsRegistryItem,
FeatureFlagState,
InfoCard,
useApi,
} from '@backstage/core';
import { List } from '@material-ui/core';
import { EmptyFlags } from './EmptyFlags';
import { FlagItem } from './FeatureFlagsItem';
type Props = { featureFlags: FeatureFlagsRegistryItem[] };
export const FeatureFlags = ({ featureFlags }: Props) => {
const featureFlagApi = useApi(featureFlagsApiRef);
export const FeatureFlags = () => {
const featureFlagsApi = useApi(featureFlagsApiRef);
const featureFlags = featureFlagsApi.getRegisteredFlags();
const initialFlagState = featureFlags.reduce(
(result, featureFlag: FeatureFlagsRegistryItem) => {
const state = featureFlagApi.getFlags().get(featureFlag.name);
const state = featureFlagsApi.getFlags().get(featureFlag.name);
result[featureFlag.name] = state;
return result;
@@ -46,17 +46,21 @@ export const FeatureFlags = ({ featureFlags }: Props) => {
const toggleFlag = useCallback(
(flagName: FeatureFlagName) => {
const newState = featureFlagApi.getFlags().toggle(flagName);
const newState = featureFlagsApi.getFlags().toggle(flagName);
setState(prevState => ({
...prevState,
[flagName]: newState,
}));
featureFlagApi.getFlags().save();
featureFlagsApi.getFlags().save();
},
[featureFlagApi],
[featureFlagsApi],
);
if (!featureFlags.length) {
return <EmptyFlags />;
}
return (
<InfoCard>
<List dense>
@@ -15,17 +15,9 @@
*/
import React, { useState } from 'react';
import {
Content,
featureFlagsApiRef,
Header,
HeaderTabs,
Page,
pageTheme,
useApi,
} from '@backstage/core';
import { Content, Header, HeaderTabs, Page, pageTheme } from '@backstage/core';
import { General } from './General';
import { AuthProviders, DefaultProviderSettings } from './AuthProviders';
import { AuthProviders } from './AuthProviders';
import { FeatureFlags } from './FeatureFlags';
type Props = {
@@ -37,9 +29,6 @@ export const SettingsPage = ({ providerSettings }: Props) => {
const onTabChange = (index: number) => {
setActiveTab(index);
};
const featureFlagsApi = useApi(featureFlagsApiRef);
const featureFlags = featureFlagsApi.getRegisteredFlags();
const providers = providerSettings ?? <DefaultProviderSettings />;
const tabs = [
{ id: 'general', label: 'General' },
@@ -49,8 +38,8 @@ export const SettingsPage = ({ providerSettings }: Props) => {
const content = [
<General />,
<AuthProviders providers={providers} />,
<FeatureFlags featureFlags={featureFlags} />,
<AuthProviders providerSettings={providerSettings} />,
<FeatureFlags />,
];
return (